数据库简介¶
信息
您是一位经验丰富的开发者,并且已经了解数据库的一切了吗? 🤓
那么您可以直接跳到下一节。
如果您不了解数据库的一切,这里有一个快速概述。
您可以稍后自行学习更多内容。
但这应该能帮助您开始使用数据库并高效地使用 SQLModel。🚀
什么是数据库¶
那么,什么是数据库呢?
数据库是一个以结构化且高效的方式存储和管理数据的系统。
提示
通常将“数据库”一词缩写为 “DB”。
由于关于数据库的信息很多,并且可能变得非常技术化和学术化,我将在这里为您快速概述一些主要概念。
我甚至会告诉您一些关于不同类型数据库的信息,包括 SQLModel 不涵盖的数据库(“NoSQL”数据库)。
为什么要使用数据库¶
在开始编程时,程序的代码之外还有一个数据库可能并不明显是个好主意。让我们从这一点开始。
提示
如果这对您来说很明显,请直接进入下一节。👇
在您的代码中,您已经有了变量、字典、列表等。它们都已经以某种方式存储了数据。为什么还需要一个单独的数据库呢?
如果您仔细观察,您的代码是静态的,一旦运行,它就不会真正随时间变化。当然,您会经常更改代码,添加功能等,但是一旦您启动 Python 运行您的代码,程序就会保持它启动时的状态。如果您更改代码,程序只有在再次运行时才会更改。
即使您更改了变量中的内容,一旦程序终止,所有在内存中的数据都将消失。🔥
在大多数情况下,您的程序的目标是处理程序外部的数据。
- 它可能只是将文件从一个位置移动到另一个位置。
- 或者它可能从终端接收用户数据并以不同方式显示。
- 或者是一个接收数据并以某种方式处理的Web API等等。
在大多数情况下,数据来自程序外部或最终在程序外部(例如,显示在屏幕上,在文件中等)。
在许多情况下,您需要您的程序能够创建和存储数据,读取它,更新它,删除它等等。
您可以通过从代码中读写文件来完成所有这些。这在简单的情况下是可行的。但对于大多数数据更为复杂的复杂系统,这种策略效率不高。并且您将不得不处理许多注意事项,保持数据同步,确保数据安全存储等等。
数据库旨在解决这些问题,使数据处理过程更加高效,并且独立于您的代码。✨
如何与数据库交互¶
有许多不同类型的数据库。
单文件数据库¶
数据库可以是一个名为 heroes.db 的单个文件,以非常高效的方式通过代码管理。SQLite 就是一个例子,稍后会详细介绍。
服务器数据库¶
数据库也可以是一个作为应用程序在服务器上运行的系统,它以优化的格式在内部处理多个文件。
就像一个网络服务器,但以自定义且高效的方式进行通信。这是最常见的数据库交互类型。
在这种情况下,您的代码将与这个服务器应用程序对话,而不是直接读取或修改文件。
数据库可能位于不同的服务器/机器上
或者数据库可能位于相同的服务器/机器上
这些类型数据库最重要的方面是,您的代码不会直接读取或修改包含数据的文件。
相反,您的代码与数据库应用程序通信,而该数据库应用程序才是实际读取和修改其数据文件的。这是因为此数据库应用程序通常比您的代码效率高得多。
一些采用这种方式工作的数据库的例子包括 PostgreSQL、MySQL 或 MongoDB。
分布式服务器¶
在某些情况下,数据库甚至可能是一组在不同机器上运行的服务器应用程序,它们协同工作并相互通信以提高效率并处理更多数据。
在这种情况下,您的代码将与运行在不同机器上的一个或多个这些服务器应用程序对话。
大多数作为服务器应用程序工作的数据库也都以一种或另一种方式支持多服务器。
拥有分布式系统也带来了额外的挑战,所以您很有可能首先会与一个单服务器应用程序或一个基于单文件的应用程序进行交互。
SQL 数据库¶
我们已经讨论了与数据库交互的不同方式以及它们如何处理文件等。这适用于大多数或所有数据库。
但是还有另一种非常重要的数据库分类方式。正如您所想,数据库类型很多,每个组中也有很多数据库。但总的来说,它们可以分为两大类:“SQL 数据库”和“NoSQL 数据库”。
我们稍后会讲到为什么叫“SQL”,但首先,让我们看看它到底是什么。
用于 SQL 数据库的 SQLModel¶
SQLModel 是一个帮助您处理 SQL 数据库的工具。
它对 NoSQL 数据库帮助不大。不过,我将在这里稍作解释。
发明 SQL 数据库¶
很久以前,一些聪明人意识到存储数据的一个好方法是将其放入不同的表中。
我所说的“表”只是一个网格中的数据,有不同的列和行,很像一个单一的电子表格。
每行代表一个特定的项目或记录。每列代表该记录的特定属性或字段。
大表示例¶
让我们想象一下,我们需要存储一些关于英雄的数据。
如果我们使用一张表来存储英雄,它可能会是这样
| id | name | secret_name | age | 团队 | 总部 |
|---|---|---|---|---|---|
| 1 | 死侍 | 戴夫·威尔逊 | 空 | Z-因子 | 玛格丽特修女酒吧 |
| 2 | 蜘蛛男孩 | 佩德罗·帕尔克多 | 空 | 阻止者 | 锐利之塔 |
| 3 | 锈人 | 汤米·夏普 | 48 | 阻止者 | 锐利之塔 |
这可能就是我们使用一张表,例如,一个电子表格时需要做的事情。
但这有一些问题。让我们看看一些问题。
单表问题¶
想象一下,他们决定将“尖塔”改名为“阻止者塔”。
现在我们必须在两个地方更新它。
如果我们的代码开始在一个地方更新这个名字,然后突然停电,电脑关机了怎么办?
我们可能会得到不一致的信息,一个地方写着“阻止者塔”,另一个地方写着“尖塔”。
| id | name | secret_name | age | 团队 | 总部 |
|---|---|---|---|---|---|
| 1 | 死侍 | 戴夫·威尔逊 | 空 | Z-部队 | 玛格丽特修女酒吧 |
| 2 | 蜘蛛男孩 | 佩德罗·帕尔克多 | 空 | 阻止者 | 阻止者塔 ✅ |
| 3 | 锈人 | 汤米·夏普 | 48 | 阻止者 | 尖塔 🚨 |
现在假设我们需要添加一个名为“麻将”的新英雄,他是“Z-Force”团队的一员。
我们可能会忘记团队的名称,最终添加一个带有无效团队名称的“麻将”,例如“Y-Force”。
| id | name | secret_name | age | 团队 | 总部 |
|---|---|---|---|---|---|
| 1 | 死侍 | 戴夫·威尔逊 | 空 | Z-部队 | 玛格丽特修女酒吧 |
| 2 | 蜘蛛男孩 | 佩德罗·帕尔克多 | 空 | 阻止者 | 阻止者塔 |
| 3 | 锈人 | 汤米·夏普 | 48 | 阻止者 | 锐利之塔 |
| 4 | 麻将 | 尼娜·瑟格尔 | 31 | Y-Force 🚨 | 玛格丽特修女酒吧 |
如果一个英雄属于两个团队怎么办?我们无法轻松地将其放入一个大表中。
多表¶
但这些和其他问题可以通过将数据存储在多个表中来更好地解决。
所以,我们不用一个包含所有数据的单一表格,我们可以为英雄创建一个表格,为团队创建一个表格,并找到一种方法将两者连接起来。
团队表可能如下所示
| id | name | 总部 |
|---|---|---|
| 1 | 阻止者 | 锐利之塔 |
| 2 | Z-部队 | 玛格丽特修女酒吧 |
现在,英雄表看起来几乎相同。但是请记住我们提到过我们需要一种连接这两个表的方法吗?
英雄表现在会有一个新的列 team_id。这个列显示了每行(每个英雄)与其所属团队之间的关系。
| id | name | secret_name | age | team_id ✨ |
|---|---|---|---|---|
| 1 | 死侍 | 戴夫·威尔逊 | 空 | 2 ✨ |
| 2 | 蜘蛛男孩 | 佩德罗·帕尔克多 | 空 | 1 ✨ |
| 3 | 锈人 | 汤米·夏普 | 48 | 1 ✨ |
标识 - 主键¶
在上面的例子中,每一行都有一个 id。每个 ID 在表中是唯一的,并标识该特定行。
这些 SQL 数据库要求有一种唯一标识表中每一行的方法。它可以是列的唯一组合,但通常只是一列。这被称为表的“主键”。
主键通常是单个列,通常由数据库自动生成的整数,在许多情况下,该列简称为 id。
这个主键,在这种情况下是 id 列,在每个表中必须是唯一的。但是两个不同的表可以有相同的 ID。例如,上面,两个表都有 ID 2,分别对应两个不同的行,一个表中的“Z-Force”和另一个表中的“Spider-Boy”,但只要每个表只有一个,这仍然是允许的。
关系 - 外键¶
表中的每行都有一个唯一的主键(在我们的例子中是一个名为 id 的列)。
例如,团队表中的 ID 1 对应团队 Preventers,ID 2 对应团队 Z-Force。
由于这些主键ID可以唯一标识团队表中的每一行,我们现在可以转到英雄表,并引用团队表中的那些ID。
因此,在英雄表中,我们使用 team_id 列来定义与团队的外部表的关系。英雄表中的 team_id 列的每个值都将与团队表中某行的 id 列的值相同。
在英雄表中,我们有一个主键,它是 id。但我们还有另一个列 team_id,它指向一个外部表中的键。这也有一个技术术语,team_id 是一个“外键”。
关系和关系型数据库¶
这些表中的每一个在技术和学术上都称为“关系”。
在讨论这些数据库时,您可能会经常听到这个词。
它没有您在英语中使用的“事物之间相关联”的含义,尽管这些表中的每一个实际上都与其他表“相关联”。
技术术语关系仅指这些表中的每一个。
正因为这个技术术语,这些 SQL 数据库也被称为关系型数据库(事实上,这是技术上正确的术语)。但它仍然只是指这些由多个表组成的数据库。
SQL - 语言¶
在开发了这些将数据存储在多个表中的想法后,他们还创建了一种可用于与这些表交互的语言。
这种语言被称为 SQL,这个名字来源于结构化查询语言。
然而,这种语言不仅用于查询数据。它还用于创建记录/行,更新它们,删除它们。以及操作数据库,创建表等。
这种语言被所有处理多表的数据库所支持,这就是它们被称为 SQL 数据库的原因。尽管每个数据库支持的 SQL 语言都有细微差别(方言)。
假设存储英雄的表名为 hero 表。一个获取其中所有数据的 SQL 查询示例如下
SELECT *
FROM hero;
该 SQL 查询将返回该表
| id | name | secret_name | age | team_id |
|---|---|---|---|---|
| 1 | 死侍 | 戴夫·威尔逊 | 空 | 2 |
| 2 | 蜘蛛男孩 | 佩德罗·帕尔克多 | 空 | 1 |
| 3 | 锈人 | 汤米·夏普 | 48 | 1 |
用于 SQL 的 SQLModel¶
SQLModel 是一个库,它帮助您使用常规 Python 对象编写 Python 代码,然后将其转换为发送到 SQL 数据库的 SQL 语句。
接下来,它接收数据并将其放入 Python 对象中,您可以继续在代码中使用这些对象。
我将在下一节中告诉您更多关于 SQL、SQLModel、如何使用它们以及它们之间关系的信息。
技术细节
SQLModel 构建在 SQLAlchemy 之上。事实上,它只是 SQLAlchemy 和 Pydantic 混合在一起,并添加了一些修饰。
NoSQL 数据库¶
尽管 SQL 数据库是最古老和最常用的数据库类型,但还有另一类(非常有趣)的数据库,那就是 NoSQL 数据库。
NoSQL 数据库涵盖了广泛的不同子类型,包括键值存储、文档存储、图数据库等等。
SQLModel 只能帮助您处理 SQL 数据库。因此,我们将在文档的其余部分讨论这些内容。