SQL Server外鍵約束

在本教學中,將學習如何使用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_groupsvendors表之間的關係是一對多的。

對於vendors表中的每一行,始終可以在vendor_groups表中找到相應的行。

但是,如果使用當前表創建方式,可以在vendors表中插入一行而不在vendor_groups表中顯示相應的行。還可以刪除vendor_groups表中的行,而無需更新或刪除vendors表中導致vendors表中存在孤立的行。

要強制執行vendor_groupsvendors表中的數據之間的鏈接,需要在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_group的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 UPDATEON DELETE指定在更新和刪除父表中的行時將執行的操作。 以下是允許的操作:NO ACTIONCASCADESET NULLSET 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為子表中的行設置默認值,這些行更新了父表中的相應行。

上一篇: SQL Server約束 下一篇: SQL Server視圖