在本教程中,将学习如何使用SQL Server外键约束来强制两个表中的数据之间的链接。
SQL Server外键约束简介
请考虑以下vendor_groups
和vendor
表,它们的结构如下:
CREATE TABLE procurement.vendor_groups (
group_id INT IDENTITY PRIMARY KEY,
group_name VARCHAR (100) NOT NULL
);
CREATE TABLE procurement.vendors (
vendor_id INT IDENTITY PRIMARY KEY,
vendor_name VARCHAR(100) NOT NULL,
group_id INT NOT NULL,
);
每个供应商属于供应商组,每个供应商组可能有零个或多个供应商。 vendor_groups
和vendors
表之间的关系是一对多的。
对于vendors
表中的每一行,始终可以在vendor_groups
表中找到相应的行。
但是,如果使用当前表创建方式,可以在vendors
表中插入一行而不在vendor_groups
表中显示相应的行。还可以删除vendor_groups
表中的行,而无需更新或删除vendors
表中导致vendors
表中存在孤立的行。
要强制执行vendor_groups
和vendors
表中的数据之间的链接,需要在vendors
表中建立外键。
外键是一个表中的一列或一组列,它唯一地标识另一个表的行(或者在自引用的情况下为同一个表)。要创建外键,请使用FOREIGN KEY
约束。
以下语句删除vendors
表并使用FOREIGN KEY
约束重新创建它:
DROP TABLE vendors;
CREATE TABLE procurement.vendors (
vendor_id INT IDENTITY PRIMARY KEY,
vendor_name VARCHAR(100) NOT NULL,
group_id INT NOT NULL,
CONSTRAINT fk_group FOREIGN KEY (group_id)
REFERENCES procurement.vendor_groups(group_id)
);
现在,vendor_groups
表称为父表,该表是外键约束引用的表。 vendors
表称为子表,该表是应用外键约束的表。
在上面的语句中,以下子句创建名为fk_grou
p的FOREIGN KEY
约束,该约束将vendors
表中的group_id
链接到vendor_groups
表中的group_id
:
CONSTRAINT fk_group FOREIGN KEY (group_id) REFERENCES procurement.vendor_groups(group_id)
SQL Server FOREIGN KEY约束语法
创建FOREIGN KEY
约束的一般语法如下:
CONSTRAINT fk_constraint_name
FOREIGN KEY (column_1, column2,...)
REFERENCES parent_table_name(column1,column2,..)
下面来详细学习一下这种语法。
首先,在CONSTRAINT
关键字后指定FOREIGN KEY
约束名称。约束名称是可选的(不用指定也可以),因此可以按如下方式定义FOREIGN KEY
约束:
FOREIGN KEY (column_1, column2,...)
REFERENCES parent_table_name(column1,column2,..)
在这种情况下,SQL Server将自动为FOREIGN KEY
约束生成名称。
其次,在FOREIGN KEY
关键字后面指定括号括起来的逗号分隔外键列的列表。
第三,指定外键引用的父表的名称以及与子表中的列具有链接的逗号分隔列的列表。
SQL Server FOREIGN KEY约束示例
首先,在vendor_groups
表中插入一些行:
INSERT INTO procurement.vendor_groups(group_name)
VALUES('第三方供应商'),
('优品供应商'),
('一次性供应商');
其次,将具有供应商组的新供应商插入vendors
表:
INSERT INTO procurement.vendors(vendor_name, group_id)
VALUES('ABC Corp', 1);
上面语句按预期工作。
第三,尝试插入vendor_groups
表中不存在供应商组的新供应商:
INSERT INTO procurement.vendors(vendor_name, group_id)
VALUES('XYZ Corp',4);
SQL Server发出以下错误:
The INSERT statement conflicted with the FOREIGN KEY constraint "fk_group". The conflict occurred in database "BikeStores", table "procurement.vendor_groups", column 'group_id'.
在此示例中,由于FOREIGN KEY
约束,vendor_groups
表中group_id
列的值为4
的行不存在。因此SQL Server拒绝插入并发出错误。
参考操作
外键约束确保了引用完整性。如果父表中存在相应的行,则只能在子表中插入一行。此外,外键约束用于在更新或删除父表中的行时定义引用操作,如下所示:
FOREIGN KEY (foreign_key_columns)
REFERENCES parent_table(parent_key_columns)
ON UPDATE action
ON DELETE action;
ON UPDATE
和ON DELETE
指定在更新和删除父表中的行时将执行的操作。 以下是允许的操作:NO ACTION
,CASCADE
,SET NULL
和SET DEFAULT
。
删除父表中行的操作
如果删除父表中的一行或多行,则可以设置以下操作之一:
ON DELETE NO ACTION
:SQL Server引发错误并回滚父表中行的删除操作。ON DELETE CASCADE
:SQL Server删除子表中与从父表中删除的行相对应的行。ON DELETE SET NULL
:如果删除父表中的相应行,则SQL Server将子表中的行设置为NULL
。 要执行此操作,外键列必须可为NULL
。ON DELETE SET DEFAULT
:如果删除父表中的相应行,SQL Server会将子表中的行设置为其默认值。 要执行此操作,外键列必须具有默认定义。 请注意,如果未指定默认值,则可空列的默认值为NULL
。
默认情况下,如果未明确指定任何操作,则SQL Server将应用ON DELETE NO ACTION
。
更新父表中行的操作
如果更新父表中的一行或多行,则可以设置以下操作之一:
ON UPDATE NO ACTION
:SQL Server引发错误并回滚父表中行的更新操作。ON UPDATE CASCADE
:当父表中的行更新时,SQL Server更新子表中的相应行。ON UPDATE SET NULL
:当更新父表中的相应行时,SQL Server将子表中的行设置为NULL。 请注意,外键列必须可以为空以便执行此操作。ON UPDATE SET DEFAULT
:SQL Server为子表中的行设置默认值,这些行更新了父表中的相应行。