欢迎来到关联式数据库的世界!
在本章中,我们将告别简单的平铺文件(flat files),深入探讨关联式数据库(relational databases)。你可以把它想象成桌上一堆杂乱的文件,与一个井然有序、所有项目都互相连接的档案柜之间的区别。数据库是现代应用程序的骨干,从 Instagram 到你学校的成绩系统,背后都少不了它。看完这些笔记后,你将学会如何整理数据,让它变得高效、准确且易于检索!
1. 什么是关联式数据库?
简单来说,关联式数据库是一种透过多个互相连接的表格来存储数据的方法。我们不再使用一个笨重且巨大的表格(即平铺文件),而是将数据拆分成更小、更合乎逻辑的表格。
比喻:想象一个音乐 App。与其建立一个包含歌曲名称、歌手、歌手年龄以及每首曲目对应专辑的巨型表格,不如分别建立“歌手 (Artists)”、“专辑 (Albums)”和“歌曲 (Songs)”三个表格。它们透过特殊的 ID 数字来建立“关联”。
你需要掌握的关键术语:
属性 (Attribute): 这是表格中列 (column) 或字段 (field) 的专业术语。它代表信息的特定类别。例如:“出生日期 (DateOfBirth)”或“姓氏 (Surname)”。
主键 (Primary Key): 这是表格中每一条记录(行)的唯一标识码。没有任何两行可以拥有相同的主键。例如:你在学校的“学生编号”。
复合主键 (Composite Primary Key): 有时,单一属性不足以保证唯一性。复合主键会结合两个或以上的属性来建立唯一标识码。例如:在“教室预订 (Classroom Booking)”表格中,结合“教室编号 (RoomNumber)”和“时段 (Period)”就可以作为一个唯一键。
外键 (Foreign Key): 这是来自另一个表格的主键,出现在当前表格中以连接两者。它就像是表格之间的“桥梁”。
快速重温:
- 主键: 自身表格中的唯一标识 ID。
- 外键: 从其他表格引入并作为连接用的主键。
重点总结: 关联式数据库透过以键值连接的多个表格,减少数据重复并保持系统条理分明。
2. 数据库设计与规范化
如果规范化 (normalisation) 这个词听起来很吓人,不用担心!这只是一个逐步“整理”数据库的过程,目的是使其达到最高效率。我们这么做是为了避免数据冗余 (data redundancy)(重复存储相同的内容)和数据不一致 (data inconsistency)(同时存在两个不同的“真实版本”)。
规范化的三个层次
为了达到第三范式 (3NF),我们需要遵循以下步骤:
第一范式 (1NF)
如果一个表格中没有重复的属性组,它就达到了 1NF。表格中的每个“单元格”都必须仅包含一个数据。
第二范式 (2NF)
如果一个表格已经达到 1NF,且所有非主键属性都完全依赖于主键,它就达到了 2NF。这通常只在你使用复合主键时才需要考虑。你不应该在表格中存储仅与主键的“一部分”相关的数据。
第三范式 (3NF)
如果一个表格已经达到 2NF,且没有传递依赖 (transitive dependencies),它就达到了 3NF。这句话用通俗的话来说就是:“所有属性必须仅依赖于主键。”如果一个属性依赖于另一个非主键属性,那么它就需要被移动到另一个独立的表格中。
3NF 记忆口诀: 一个著名的记忆方式是,所有数据都必须依赖于:
“主键、完整主键,且除了主键别无其他”(The Key, the Whole Key, and Nothing But the Key)。
为什么要进行规范化?
1. 节省空间: 不需要重复输入相同的地址或名称。
2. 数据完整性: 如果客户更改了电话号码,你只需要在一个地方更新,而不用更改五十次。
3. 搜索更便捷: 对计算机而言,处理规模更小、结构更清晰的表格速度更快。
重点总结: 规范化 (1NF -> 2NF -> 3NF) 能清除混乱的重复数据,并确保每一份数据都存储在最合理的逻辑位置。
3. 结构化查询语言 (SQL)
SQL 是我们用来与数据库“对话”的语言。你需要知道如何执行四项主要操作(CRUD:建立、读取、更新、删除)以及如何建立表格。
定义表格
要建立新表格,我们使用 CREATE TABLE。
范例:
CREATE TABLE Students (
StudentID INT PRIMARY KEY,
FirstName VARCHAR(20),
Surname VARCHAR(20)
);
管理数据
SELECT: 用于搜索并显示数据。
SELECT FirstName FROM Students WHERE Surname = 'Smith';
INSERT: 用于新增记录。
INSERT INTO Students (StudentID, FirstName, Surname) VALUES (101, 'Ali', 'Khan');
UPDATE: 用于更改现有数据。
UPDATE Students SET Surname = 'Jones' WHERE StudentID = 101;
DELETE: 用于删除记录。
DELETE FROM Students WHERE StudentID = 101;
必须避免的常见错误: 使用 UPDATE 或 DELETE 时,永远记得带上你的 WHERE 子句!如果你忘了它,你可能会不小心删除数据库中的所有人,或是把所有人的名字都改成 'Jones'。
重点总结: SQL 是定义表格与操控内部数据的标准语言。
4. 客户端-服务器数据库
在现实世界中,许多人(客户端)会同时尝试访问同一个数据库(服务器)。这可能会导致“交通堵塞”,我们称为并发问题 (concurrency issues)。
问题:丢失更新 (Lost Updates)
想象一下,两人在同一毫秒尝试预订航班上的最后一个座位。如果系统不够严谨,可能会同时让两人预订成功,或者其中一人的预订“覆盖”了另一人的结果。这就是丢失更新。
解决方案:
为了确保数据安全(维持完整性),我们使用以下方法:
记录锁定 (Record Locks): 当某人正在编辑记录时,数据库会将其“锁定”,直到该操作完成,否则其他人无法进行任何修改。这就像从图书馆借书一样;在你还书之前,没人能读那本书。
序列化 (Serialisation): 确保交易(transactions)是一个接一个处理,而不是同时进行,这样它们就不会互相干扰。
时间戳排序 (Timestamp Ordering): 每项交易都会获得一个“时间贴纸”。如果两人尝试更改同一数据,拥有较早时间戳的交易会先被处理。
提交排序 (Commitment Ordering): 交易会根据其依赖关系以及它们“提交”(最终确定)的时间进行排序,以确保它们不会发生冲突。
你知道吗? 银行每秒都在使用这些技术,以确保当你和朋友同时转账时,你的账户余额不会意外翻倍(或者凭空消失!)。
重点总结: 并发访问可能会破坏数据。我们使用锁定与排序技术来确保每一次更新都能正确处理,不会丢失数据。