在本教學中,將學習如何使用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為子表中的行設置默認值,這些行更新了父表中的相應行。