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