欢迎来到“关系型数据库”的世界!

同学们大家好!你有没有想过,Instagram 或 YouTube 这些网站是怎样有效率地管理数以百万计的用户、相片和留言呢?他们可不是单纯用一张巨型电子表格呢!他们用的是更聪明、更有条理的东西:就是“关系型数据库”。在这一章,我们会揭开神秘面纱,看看这些数据库究竟是怎样运作的。即使听起来有点复杂,也别担心;我们会用简单易明、贴近生活的例子来为你逐步解说。准备好了吗?我们开始吧!


数据库的基本构成要素

想象一下你在玩 LEGO 乐高积木。在搭建城堡之前,你必须先了解各种积木的样子。数据库也是一样!现在,就让我们来学习一下这些基本“积木”吧。

实体:我们存储数据的“对象”

实体”简单来说,就是你想存储数据的“人、地方、物件、事件或概念”。它通常是一个数据表的主要“主题”。

  • 例子:在一个学校数据库中,主要实体会是“学生”、“教师”和“课程”。
  • 例子:在一个图书馆数据库中,实体可能是“书籍”和“会员”。

属性:这些“对象”的详细信息

属性”是实体的“特征”或“性质”。你可以把属性想象成数据表中用来描述实体的“字段”。

  • 例子:对于“学生”这个实体,其属性可以是“学生编号”、“姓名”、“出生日期”和“班级”。
  • 例子:对于“书籍”这个实体,属性可以是“书籍编号”、“书名”和“作者”。
类比时间:你的手机联系人

想想你手机里的联系人列表。每个“联系人”都是一个“实体”。而你为每个联系人存储的详细资料,像是他们的“姓名”、“电话号码”和“电子邮箱地址”,就是“属性”。很简单吧?


重点提示

实体是名词(你想要追踪的“对象”),而属性则是形容词(这些对象的“描述”)。


数据库的核心:键 (Keys)!

想象一下学校里有三位学生都叫“陈大文”。你怎么知道你说的是哪一位?你需要一个独特的识别码。在数据库中,我们就用“键 (Keys)”来达到这个目的。

主键 (Primary Key)(数据表的“大佬”)

主键 (Primary Key, PK)”是一个(或一组)属性,它能够在数据表中“独一无二”地识别每一条记录。它是最终极的独特识别码。

主键有两条非常重要的规则:

  1. 每条记录的它都必须是独一无二的。(没有两位学生可以拥有相同的学生编号。)
  2. 不能是空值 (NULL)。(每位学生都“必须”有一个学生编号。)
  • 例子:在“`学生 (Students)`”数据表中,“学生编号 (StudentID)”会是一个完美的主键。学生的姓名就不是一个好选择,因为姓名可能会重复。

候选键 (Candidate Key)(潜在的“大佬”们)

候选键 (Candidate Key)”是任何“可能”成为主键的属性。它也必须是每条记录中独一无二的。一个数据表可以有多个候选键,但你只能选择其中一个作为官方的主键。

  • 例子:在“`学生 (Students)`”数据表中,“学生编号 (StudentID)”和“香港身份证号码 (HKID_Number)”对于每位学生来说都是独一无二的。它们都是候选键。我们可能会选择“学生编号”作为主键,因为它与学校的关联性更高。

外键 (Foreign Key)(连接的“桥梁”)

外键 (Foreign Key, FK)”是让数据库变得“关系型”的秘密武器。它是一种用来连接两个数据表的键。外键简单来说,就是一个数据表的主键被复制到另一个数据表中,用来建立关联。

  • 例子:假设我们有一个“`图书借阅 (Book_Loans)`”数据表,用来追踪哪些学生借了哪些书。我们会包含“学生编号 (StudentID)”(来自“`学生 (Students)`”数据表)和“书籍编号 (BookID)”(来自“`书籍 (Books)`”数据表)。在这里,“学生编号”和“书籍编号”在“`图书借阅`”数据表中就是外键。它们就像桥梁一样,将特定的借阅记录与特定的学生和特定的书籍连接起来。
记忆小贴士:键 (Keys)

Primary Key(主键)= 数据表的Principal(主要),独特的识别码。
Foreign Key(外键)= 来自Foreign(外部)数据表的键,用来建立桥梁。

快速回顾:键的种类

主键 (Primary Key): 数据表的主要、独特识别码(例如,`学生 (Students)` 数据表中的 `学生编号 (StudentID)`)。
候选键 (Candidate Key): 任何可能成为主键的字段(例如,`学生编号 (StudentID)` 或 `香港身份证号码 (HKID_Number)`)。
外键 (Foreign Key): 来自另一个数据表的主键,用来连接数据表(例如,`图书借阅 (Book_Loans)` 数据表中的 `学生编号 (StudentID)`)。


串联点滴:关系与组织

“关系型”数据库的重点,就是把数据存储在独立、有条理的数据表中,然后在它们之间建立“关系”。这样能避免混乱,让数据井井有条。

建立一个简单的关系型数据库

想象你经营一家小商店,并使用一张单一的电子表格来追踪销售情况。它可能如下所示:

销售编号:101, 顾客姓名:Tom, 顾客电话:555-1234, 商品:苹果, 价格:5, 数量:10
销售编号:102, 顾客姓名:Mary, 顾客电话:555-5678, 商品:橙, 价格:4, 数量:20
销售编号:103, 顾客姓名:Tom, 顾客电话:555-1234, 商品:橙, 价格:4, 数量:15

有没有发现问题?Tom 的姓名和电话号码重复出现了。如果他更改了电话号码,你必须找到所有出现过的地方并更新!这就是所谓的“数据冗余”。关系型数据库就能解决这个问题。

第一步:识别实体。在这里,我们有“`顾客 (Customers)`”、“`产品 (Products)`”和“`销售 (Sales)`”。

第二步:为每个实体建立一个独立的数据表。

  • `顾客 (Customers)` 数据表:`顾客编号 (CustomerID)` (主键), `顾客姓名 (CustomerName)`, `顾客电话 (CustomerPhone)`
  • `产品 (Products)` 数据表:`产品编号 (ProductID)` (主键), `商品名称 (ItemName)`, `价格 (Price)`
  • `销售 (Sales)` 数据表:`销售编号 (SaleID)` (主键), `顾客编号 (CustomerID)` (外键), `产品编号 (ProductID)` (外键), `数量 (Quantity)`

第三步:利用外键建立关系。

“`销售`”数据表使用 `顾客编号` 指向“`顾客`”数据表,并使用 `产品编号` 指向“`产品`”数据表。现在,Tom 的数据只会存储一次。如果他更改电话号码,你只需要在一个地方更新就可以了!这就是我们如何合理地组织数据建立关系的方法。


保持数据的干净与可靠:数据完整性

数据完整性就是要确保数据库中的数据是准确、一致且可靠的。你可以把这些想象成数据库必须遵守的严格“规则”。

实体完整性 (Entity Integrity)(“没有无名公民”规则)

这条规则很简单:数据表的主键不能是空值 (NULL)。这确保了每条记录都有一个独特的身份,并且可以被找到。这就像是说,一个国家里的每个公民都必须有一个身份证号码。

参照完整性 (Referential Integrity)(“没有幽灵参照”规则)

这是针对外键的规则。它指出外键必须符合以下其中一项:

  1. 与它所指向的数据表中现有的主键值相符。
  2. 是空值 (NULL)(如果允许的话)。

例子:你不能在“`图书借阅 (Book_Loans)`”数据表中添加一条 `学生编号 (StudentID)` 为“S1234”的记录,如果“`学生 (Students)`”数据表中没有这个编号的学生。这可以防止出现指向不明的“孤立”记录,确保所有链接都是有效的。

域完整性 (Domain Integrity)(“放对盒子”规则)

这条规则确保一个字段中的所有值都具有正确的数据类型,并且来自一个允许值集合,这个集合称为“域 (Domain)”。

  • ”是一个属性所有可能合法值的集合。
  • 例子:一个“性别 (Gender)”属性的域可以是集合 {'M', 'F'}。域完整性会阻止有人在这个字段输入“Cat”。
  • 例子:一个“分数 (Score)”属性的域可能是 0 到 100 之间的整数。你不能输入 101 或“Hello”。
重点提示

完整性规则就是数据库的“警察”!实体完整性保护主键,参照完整性保护外键的关系,而域完整性则保护字段中的数据。


加快速度:索引

想象一下,如果你要在一本没有索引的 1,000 页书中找到一个特定的词语,你可能要翻遍每一页!数据库中的“索引 (Index)”运作方式就跟教科书最后面的索引一样。

  • 它是一个特殊的查找表,数据库的搜索引擎可以利用它来加快数据检索的速度。
  • 数据库可以利用索引直接找到数据的位置,而不用搜索数据表中的每一行(这称为“全表扫描”)。
  • 索引通常建立在那些经常被用作搜索条件的字段上,例如姓名、编号或日期。

你知道吗?数据库会自动为主键建立索引,因为它是最常用来查找记录的方式!


糟糕!那个“还原”按钮:回溯

如果你在进行一个关键操作的过程中突然停电了怎么办?想想银行转账:钱从你的账户扣除了,但在存入你朋友的账户之前,系统却崩溃了。你肯定不希望你的钱就这样消失了吧!

这就是交易 (transactions) 和回溯 (rollbacks) 派上用场的地方。“交易”是一系列数据库操作,这些操作必须作为一个单一的、“要么全部完成,要么全部不完成”的单元来执行。

回溯的目的

回溯”是一个指令,用于撤销一个未能成功完成的交易所做的所有更改。它的主要目的是:

  • 撤销更改: 如果交易的任何部分失败了(或用户取消了它),就会执行回溯,将数据库恢复到交易开始之前的状态。
  • 确保数据一致性: 它防止数据库处于不完整或不一致的状态。在我们的银行例子中,回溯会把钱退回你的账户,就像转账从未发生过一样。
  • 维护完整性: 它通过确保只有完整、成功的操作才被永久存储,从而保护数据的完整性。
重点提示

回溯”是数据库交易的终极“还原”按钮。它是一个安全网,确保你的数据即使在出现问题时也能保持一致和正确。