MySQL 支援外來鍵,允許跨資料表交叉參照相關資料,以及外來鍵限制,有助於保持相關資料的一致性。
外來鍵關係涉及一個保存初始欄位值的父資料表,以及一個其欄位值參照父資料表欄位值的子資料表。外來鍵限制定義於子資料表上。
以下範例透過單一欄位外來鍵關聯 parent
和 child
資料表,並展示外來鍵限制如何強制參照完整性。
使用以下 SQL 陳述式建立父資料表和子資料表
CREATE TABLE parent (
id INT NOT NULL,
PRIMARY KEY (id)
) ENGINE=INNODB;
CREATE TABLE child (
id INT,
parent_id INT,
INDEX par_ind (parent_id),
FOREIGN KEY (parent_id)
REFERENCES parent(id)
) ENGINE=INNODB;
像這樣,將一列插入父資料表中
mysql> INSERT INTO parent (id) VALUES ROW(1);
驗證資料是否已插入。您只需從 parent
中選取所有列即可,如下所示
mysql> TABLE parent;
+----+
| id |
+----+
| 1 |
+----+
使用以下 SQL 陳述式,將一列插入子資料表中
mysql> INSERT INTO child (id,parent_id) VALUES ROW(1,1);
插入操作成功,因為父資料表中存在 parent_id
1。
若在父資料表中不存在 parent_id
值的狀況下,嘗試將列插入子資料表中,會遭到拒絕並出現錯誤,如下所示
mysql> INSERT INTO child (id,parent_id) VALUES ROW(2,2);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails
(`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`)
REFERENCES `parent` (`id`))
操作失敗,因為父資料表中不存在指定的 parent_id
值。
嘗試從父資料表中刪除先前插入的資料列也會失敗,如下所示
mysql> DELETE FROM parent WHERE id VALUES = 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`))
此操作失敗,因為子資料表中的記錄包含參照的 id (parent_id
) 值。
當操作影響父資料表中具有相符子資料列的鍵值時,結果取決於 FOREIGN KEY
子句的 ON UPDATE
和 ON DELETE
子句所指定的參照動作。省略 ON DELETE
和 ON UPDATE
子句 (如同目前子資料表定義) 等同於指定 RESTRICT
選項,這會拒絕影響父資料表中具有相符資料列的鍵值的操作。
為了演示 ON DELETE
和 ON UPDATE
參照動作,請刪除子資料表並重新建立它,以包含具有 CASCADE
選項的 ON UPDATE
和 ON DELETE
子句。CASCADE
選項會在刪除或更新父資料表中的資料列時,自動刪除或更新子資料表中相符的資料列。
DROP TABLE child;
CREATE TABLE child (
id INT,
parent_id INT,
INDEX par_ind (parent_id),
FOREIGN KEY (parent_id)
REFERENCES parent(id)
ON UPDATE CASCADE
ON DELETE CASCADE
) ENGINE=INNODB;
使用此處所示的陳述式,將一些資料列插入子資料表中
mysql> INSERT INTO child (id,parent_id) VALUES ROW(1,1), ROW(2,1), ROW(3,1);
驗證資料是否已插入,如下所示
mysql> TABLE child;
+------+-----------+
| id | parent_id |
+------+-----------+
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
+------+-----------+
使用此處所示的 SQL 陳述式,更新父資料表中的 ID,將其從 1 變更為 2
mysql> UPDATE parent SET id = 2 WHERE id = 1;
從父資料表中選取所有列,驗證更新是否成功,如下所示
mysql> TABLE parent;
+----+
| id |
+----+
| 2 |
+----+
驗證 ON UPDATE CASCADE
參照動作是否已更新子資料表,如下所示
mysql> TABLE child;
+------+-----------+
| id | parent_id |
+------+-----------+
| 1 | 2 |
| 2 | 2 |
| 3 | 2 |
+------+-----------+
為了演示 ON DELETE CASCADE
參照動作,請從 parent_id = 2
的父資料表中刪除記錄;這會刪除父資料表中的所有記錄。
mysql> DELETE FROM parent WHERE id = 2;
由於子資料表中的所有記錄都與 parent_id = 2
相關聯,ON DELETE CASCADE
參照動作會從子資料表中移除所有記錄,如下所示
mysql> TABLE child;
Empty set (0.00 sec)
有關外來鍵限制的詳細資訊,請參閱 第 15.1.20.5 節,「外來鍵限制」。