MySQL 外鍵約束的實作在以下主要方面與 SQL 標準不同
如果父表格中有數個具有相同參考鍵值的資料列,
InnoDB
會執行外鍵檢查,如同其他具有相同鍵值的父資料列不存在一樣。例如,如果您定義了RESTRICT
類型的約束,並且有一個子資料列具有數個父資料列,InnoDB
不允許刪除任何父資料列。以下範例顯示此情況mysql> CREATE TABLE parent ( -> id INT, -> INDEX (id) -> ) ENGINE=InnoDB; Query OK, 0 rows affected (0.04 sec) mysql> CREATE TABLE child ( -> id INT, -> parent_id INT, -> INDEX par_ind (parent_id), -> FOREIGN KEY (parent_id) -> REFERENCES parent(id) -> ON DELETE RESTRICT -> ) ENGINE=InnoDB; Query OK, 0 rows affected (0.02 sec) mysql> INSERT INTO parent (id) -> VALUES ROW(1), ROW(2), ROW(3), ROW(1); Query OK, 4 rows affected (0.01 sec) Records: 4 Duplicates: 0 Warnings: 0 mysql> INSERT INTO child (id,parent_id) -> VALUES ROW(1,1), ROW(2,2), ROW(3,3); Query OK, 3 rows affected (0.01 sec) Records: 3 Duplicates: 0 Warnings: 0 mysql> DELETE FROM parent WHERE id=1; ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`) ON DELETE RESTRICT)
如果
ON UPDATE CASCADE
或ON UPDATE SET NULL
遞迴以更新先前在相同階層期間已更新的相同表格,則其行為類似RESTRICT
。這表示您不能使用自我參考的ON UPDATE CASCADE
或ON UPDATE SET NULL
作業。這是為了防止級聯更新導致無限迴圈。另一方面,自我參考的ON DELETE SET NULL
是可能的,自我參考的ON DELETE CASCADE
也是如此。階層操作的巢狀層級不得超過 15 層。在插入、刪除或更新多個資料列的 SQL 陳述式中,會逐列檢查外鍵約束(如唯一約束)。在執行外鍵檢查時,
InnoDB
會在它必須檢查的子或父記錄上設定共用的資料列層級鎖定。MySQL 會立即檢查外鍵約束;檢查不會延遲到交易提交。根據 SQL 標準,預設行為應該是延遲檢查。也就是說,只有在處理完整個 SQL 陳述式後才會檢查約束。這表示無法使用外鍵刪除參考自身的資料列。沒有任何儲存引擎(包括
InnoDB
)會辨識或強制執行參考完整性約束定義中使用的MATCH
子句。使用明確的MATCH
子句不會產生指定的效果,並且會導致忽略ON DELETE
和ON UPDATE
子句。應避免指定MATCH
。SQL 標準中的
MATCH
子句會控制在與參考表格中的主鍵比較時,如何處理複合式(多欄)外鍵中的NULL
值。MySQL 基本上會實作MATCH SIMPLE
定義的語意,該語意允許外鍵全部或部分為NULL
。在這種情況下,即使它與參考的(父)表格中的任何資料列都不符,仍然可以插入包含此外鍵的(子表格)資料列。(可以使用觸發程序實作其他語意。)參考非
UNIQUE
鍵的FOREIGN KEY
約束不是標準 SQL,而是InnoDB
擴充功能,現在已棄用,且必須透過設定restrict_fk_on_non_standard_key
來啟用。您應該預期未來版本的 MySQL 將移除對使用非標準金鑰的支援,並立即遷移離開它們。根據 SQL 標準,
NDB
儲存引擎需要在任何參考為外鍵的欄位上,使用明確的唯一索引鍵(或主鍵)。對於不支援外鍵的儲存引擎(例如
MyISAM
),MySQL 伺服器會剖析並忽略外鍵規格。先前版本的 MySQL 會剖析但忽略「內嵌
REFERENCES
規格」(如 SQL 標準中定義),其中參考定義為欄位規格的一部分。MySQL 9.0 接受此類REFERENCES
子句,並強制執行由此建立的外鍵。此外,MySQL 9.0 允許隱式使用父表格的主鍵。這表示下列語法有效CREATE TABLE person ( id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT, name CHAR(60) NOT NULL, PRIMARY KEY (id) ); CREATE TABLE shirt ( id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT, style ENUM('tee', 'polo', 'dress') NOT NULL, color ENUM('red', 'blue', 'yellow', 'white', 'black') NOT NULL, owner SMALLINT UNSIGNED NOT NULL REFERENCES person, PRIMARY KEY (id) );
您可以透過檢查
SHOW CREATE TABLE
或DESCRIBE
的輸出,來了解這是否有效,如下所示mysql> SHOW CREATE TABLE shirt\G *************************** 1. row *************************** Table: shirt Create Table: CREATE TABLE `shirt` ( `id` smallint unsigned NOT NULL AUTO_INCREMENT, `style` enum('tee','polo','dress') NOT NULL, `color` enum('red','blue','yellow','white','black') NOT NULL, `owner` smallint unsigned NOT NULL, PRIMARY KEY (`id`), KEY `owner` (`owner`), CONSTRAINT `shirt_ibfk_1` FOREIGN KEY (`owner`) REFERENCES `person` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
如需外鍵約束的詳細資訊,請參閱 第 15.1.20.5 節,「外鍵約束」。