在本教學中,您將了解MySQL外來鍵(foreign key)以及如何在MySQL中建立,新增和刪除外來鍵約束。
外來鍵表示一個表中的一個欄位被另一個表中的一個欄位參照。外來鍵對相關表中的資料造成了限制,使MySQL能夠保持參照完整性。
下面來看看範例資料庫(yiibaidb)中的以下資料庫中兩個表:customers
和`orders``的ER圖。
上圖中有兩張表:customers
和orders
。每個客戶有零個或多個訂單,每個訂單只屬於一個客戶。customers
表和orders
表之間的關係是一對多的,它是由customerNumber
欄位指定在orders
表中建立外來鍵(參照customers
表的customerNumber
欄位)。orders
表中的customerNumber
欄位與customers
表中的customerNumber
主鍵欄位相關。
customers
表稱為父表或參照表,orders
表稱為子表或參照表。
表可以有多個外來鍵,子表中的每個外來鍵可能參照不同的父表。
子表中的行必須包含父表中存在的值,例如,orders
表中的每個訂單記錄必須在customers
表中存在customerNumber
。 因此,多個訂單可以指同一個客戶,因此這種關係稱為一個(客戶)到許多(訂單)或一對多。
有時,子表和父表是一樣的。外來鍵返回到表的主鍵,例如以下employees
表:
reportTo
列是一個參照employeeNumber
列的外來鍵,employeeNumber
列是employees
表的主鍵,以反映員工之間的報告結構,即每個員工向另一個員工傳送的報告和員工可以有零個或多個直接報告。有關如何使用有,請參考自連線教學,以幫助您根據這種表查詢來查詢相關資料。
reportTo
外來鍵也稱為遞回或自參照外來鍵。
外來鍵執行參照完整性,可以幫助您自動維護資料的一致性和完整性。 例如,不能為不存在的客戶建立訂單。
此外,可以為customerNumber
外來鍵設定級聯刪除操作,以便在customers
表中刪除客戶時,與客戶關聯的所有訂單也將被刪除。 這樣可以節省您使用多個DELETE語句或DELETE JOIN語句的時間和精力。
與刪除相同,還可以為customerNumber
外來鍵定義級聯更新操作,以執行交叉表更新,而不使用多個UPDATE語句或UPDATE JOIN語句。
在MySQL中,InnoDB儲存引擎支援外來鍵,因此您必須建立InnoDB表才能使用外來鍵約束。
MySQL建立外來鍵語法
以下語法說明了如何在CREATE TABLE語句中的子表中定義外來鍵。
CONSTRAINT constraint_name
FOREIGN KEY foreign_key_name (columns)
REFERENCES parent_table(columns)
ON DELETE action
ON UPDATE action
下面我們來更詳細的檢視上面語法:
CONSTRAINT
子句允許您為外來鍵約束定義約束名稱。如果省略它,MySQL將自動生成一個名稱。FOREIGN KEY
子句指定子表中參照父表中主鍵列的列。您可以在FOREIGN KEY
子句後放置一個外來鍵名稱,或者讓MySQL為您建立一個名稱。 請注意,MySQL會自動建立一個具有foreign_key_name
名稱的索引。REFERENCES
子句指定父表及其子表中列的參照。 在FOREIGN KEY
和REFERENCES
中指定的子錶和父表中的列數必須相同。ON DELETE
子句允許定義當父表中的記錄被刪除時,子表的記錄怎樣執行操作。如果省略ON DELETE
子句並刪除父表中的記錄,則MySQL將拒絕刪除子表中相關聯的資料。此外,MySQL還提供了一些操作,以便您可以使用其他選項,例如ON DELETE CASCADE,當刪除父表中的記錄時,MySQL可以刪除子表中參照父表中記錄的記錄。 如果您不希望刪除子表中的相關記錄,請改用ON DELETE SET NULL
操作。當父表中的記錄被刪除時,MySQL會將子表中的外來鍵列值設定為NULL
,條件是子表中的外來鍵列必須接受NULL
值。 請注意,如果使用ON DELETE NO ACTION
或ON DELETE RESTRICT
操作,MySQL將拒絕刪除。ON UPDATE
子句允許指定在父表中的行更新時,子表中的行會怎樣執行操作。當父表中的行被更新時,可以省略ON UPDATE
子句讓MySQL拒絕對子表中的行的任何更新。 ON UPDATE CASCADE
操作允許您執行交叉表更新,並且當更新父表中的行時,ON UPDATE SET NULL
操作會將子表中行中的值重置為NULL
值。 ON UPDATE NO ACTION
或UPDATE RESTRICT
操作拒絕任何更新。MySQL建立表外來鍵範例
以下範例建立一個dbdemo
資料庫和兩個表:categories
和products
。每個類別都有一個或多個產品,每個產品只屬於一個類別。 products
表中的cat_id
欄位被定義為具有UPDATE ON CASCADE
和DELETE ON RESTRICT
操作的外來鍵。
CREATE DATABASE IF NOT EXISTS dbdemo;
USE dbdemo;
CREATE TABLE categories(
cat_id int not null auto_increment primary key,
cat_name varchar(255) not null,
cat_description text
) ENGINE=InnoDB;
CREATE TABLE products(
prd_id int not null auto_increment primary key,
prd_name varchar(355) not null,
prd_price decimal,
cat_id int not null,
FOREIGN KEY fk_cat(cat_id)
REFERENCES categories(cat_id)
ON UPDATE CASCADE
ON DELETE RESTRICT
)ENGINE=InnoDB;
MySQL新增外來鍵語法
要將外來鍵新增到現有表中,請使用ALTER TABLE語句與上述外來鍵定義語法:
ALTER table_name
ADD CONSTRAINT constraint_name
FOREIGN KEY foreign_key_name(columns)
REFERENCES parent_table(columns)
ON DELETE action
ON UPDATE action;
MySQL新增外來鍵範例
現在,我們新增一個名為vendors
的新表,並更改products
表以包含供應商ID
欄位:
USE dbdemo;
CREATE TABLE vendors(
vdr_id int not null auto_increment primary key,
vdr_name varchar(255)
)ENGINE=InnoDB;
ALTER TABLE products
ADD COLUMN vdr_id int not null AFTER cat_id;
要在products
表中新增外來鍵,請使用以下語句:
ALTER TABLE products
ADD FOREIGN KEY fk_vendor(vdr_id)
REFERENCES vendors(vdr_id)
ON DELETE NO ACTION
ON UPDATE CASCADE;
現在,products
表有兩個外來鍵,一個是參照categories
表,另一個是參照vendors
表。
您還可以使用ALTER TABLE
語句將外來鍵刪除,如下語句:
ALTER TABLE table_name
DROP FOREIGN KEY constraint_name;
在上面的宣告中:
DROP FOREIGN KEY
子句之後。請注意,
constraint_name
是在建立或新增外來鍵到表時指定的約束的名稱。 如果省略它,MySQL會為您生成約束名稱。
要獲取生成的表的約束名稱,請使用SHOW CREATE TABLE
語句,如下所示:
SHOW CREATE TABLE table_name;
例如,要檢視products
表的外來鍵,請使用以下語句:
SHOW CREATE TABLE products;
以下是語句的輸出:
CREATE TABLE products (
prd_id int(11) NOT NULL AUTO_INCREMENT,
prd_name varchar(355) NOT NULL,
prd_price decimal(10,0) DEFAULT NULL,
cat_id int(11) NOT NULL,
vdr_id int(11) NOT NULL,
PRIMARY KEY (prd_id),
KEY fk_cat (cat_id),
KEY fk_vendor(vdr_id),
CONSTRAINT products_ibfk_2
FOREIGN KEY (vdr_id)
REFERENCES vendors (vdr_id)
ON DELETE NO ACTION
ON UPDATE CASCADE,
CONSTRAINT products_ibfk_1
FOREIGN KEY (cat_id)
REFERENCES categories (cat_id)
ON UPDATE CASCADE
) ENGINE=InnoDB;
products
表有兩個外來鍵約束:products_ibfk_1
和products_ibfk_2
。
可以使用以下語句刪除products
表的外來鍵:
ALTER TABLE products
DROP FOREIGN KEY products_ibfk_1;
ALTER TABLE products
DROP FOREIGN KEY products_ibfk_2;
有時,因為某種原因需要禁用外來鍵檢查(例如將CSV檔案中的資料匯入表中)非常有用。 如果不禁用外來鍵檢查,則必須以正確的順序載入資料,即必須首先將資料載入到父表中,然後再將資料載入匯入到子表中,這可能是乏味的。 但是,如果禁用外來鍵檢查,則可以按任何順序載入匯入資料。
除非禁用外來鍵檢查,否則不能刪除由外來鍵約束參照的表。刪除表時,還會刪除為表定義的任何約束。
要禁用外來鍵檢查,請使用以下語句:
SET foreign_key_checks = 0;
當然,可以使用以下語句啟用它:
SET foreign_key_checks = 1;
在本教學中,我們已經介紹了很多有關MySQL外來鍵的內容。還向您介紹了一些非常方便的語句,允許您在MySQL中有效地管理外來鍵。