数据库完整性控制
了解数据库的另一件重要事情是 CONSTRAINS。在约束的帮助下,您可以控制表中的数据更改并保持它们的完整性和一致性。
当我们谈论数据库时,什么是数据一致性?
让我们以带有员工、产品和任务表的在线商店为例。我们已经知道任务表中可能存在未分配给任何人的任务:此类行的 employee_id为 NULL。
但是如果任务表中有一个条目的 employee_id 等于,比方说,115,会发生什么?毕竟,我们没有这样的员工。employee 表中没有 id = 115 的员工。同时,任务表中有指向具有此 ID 的员工的链接。这是一个数据不一致的例子。
那么我们如何协调这些数据呢?理想情况下,SQL 服务器可以在任何数据更改时控制所有这些细微差别。而有这样一个机会,它叫做FOREIGN_KEY。
如果表中的某些列不仅包含数字,还包含来自另一个表的 id 行,则可以明确指定。
添加外键
这样的键可以在创建阶段和之后使用 ALTER TABLE 添加到表中。格式没有根本的不同。我们将介绍这两种选择。
这种键/规则的一般形式是:
FOREIGN KEY (column)
REFERENCES table(column)
让我们将此键/规则添加到任务表中,以确保表中的所有employee_id都引用员工表中的现有条目。该脚本将如下所示:
ALTER TABLE task
ADD FOREIGN KEY (employee_id)
REFERENCES employee(id)
如果我们决定在创建任务表时添加这条规则,那么代码将如下所示:
CREATE TABLE task (
id INT,
name VARCHAR(100),
employee_id INT,
deadline DATE,
PRIMARY KEY (id),
FOREIGN KEY (employee_id)
REFERENCES employee(id)
);
顺便说一句,在某些情况下,我们引用的字符串具有唯一的复合键:例如,“姓名和出生年份”或“productCatogoryId 和 productId”。那么FOREIGN KEY可以这样写:
FOREIGN KEY (our_column1, our_column2)
REFERENCES table(their_column1, their_column2)
外键和更改数据
现在想象一下我们决定更新员工表中的一些数据并且我们的员工 ID 发生变化的情况。任务表中的数据会发生什么变化?没错,它们将变得无关紧要,我们数据库的完整性将受到侵犯。
为防止这种情况发生,您可以告诉 SQL Server 在 employee 表中的 id 更改时更改所有表中引用此特定已更改 id 的所有行的 employee_id。
此类脚本称为OnUpdate和OnDelete。记录id改变了怎么办,记录被删除了怎么办?
随着删除,并非一切都那么简单。如果数据库中有由字符串表示的相互引用的依赖对象,则在删除一个对象时可能会出现多种行为场景。
假设我们删除了一个网站用户,这意味着我们必须删除他所有的个人信件。但我们不太可能删除他所有的公开评论。
或者员工离职。如果他辞职了,同时分配给他的所有任务都从数据库中消失了,那才奇怪。但如果他们不是由他任命,结果也会很糟糕。更正确的做法是让员工在将所有任务重新分配给其他人后可以辞职。
以下是我们如何使用 FOREIGN KEY 描述这些场景。这种键/规则的一般形式是:
FOREIGN KEY (column)
REFERENCES table(column)
[ON DELETE reference_option]
[ON UPDATE reference_option]
如果删除(ON DELETE)或更改(ON UPDATE)记录怎么办?SQL 服务器总共可以有 5 个选项来处理这些情况中的每一个:
# | 参考选项 | 解释 |
---|---|---|
1个 | 限制 | 如果找到字符串引用则禁用操作 |
2个 | 级联 | 更改依赖行中的 id |
3个 | 设置为空 | 将依赖行中的 id 设置为 NULL |
4个 | 无动作 | 没事做 |
5个 | 设置默认 x | 将依赖汇中的 id 设置为 x |
下面是我们如何修改我们的任务表:
ALTER TABLE task
ADD FOREIGN KEY (employee_id)
REFERENCES employee(id)
ON UPDATE CASCADE
ON DELETE RESTRICT;
这里写了什么:
ON UPDATE CASCADE:如果 employee 表中的 id 键发生变化,则也更改引用它的任务表中的 employee_id 。
ON DELETE RESTRICT:如果正在从员工表中删除一行并从任务表中引用该行,则防止从员工表中删除该行。
GO TO FULL VERSION