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 節,「外鍵約束」。