相關文件 下載本手冊
PDF (US Ltr) - 39.9Mb
PDF (A4) - 40.0Mb
Man Pages (TGZ) - 258.5Kb
Man Pages (Zip) - 365.5Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 參考手冊  /  ...  /  使用外來鍵

5.6.6 使用外來鍵

MySQL 支援外來鍵,允許跨資料表交叉參照相關資料,以及外來鍵限制,有助於保持相關資料的一致性。

外來鍵關係涉及一個保存初始欄位值的父資料表,以及一個其欄位值參照父資料表欄位值的子資料表。外來鍵限制定義於子資料表上。

以下範例透過單一欄位外來鍵關聯 parentchild 資料表,並展示外來鍵限制如何強制參照完整性。

使用以下 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 UPDATEON DELETE 子句所指定的參照動作。省略 ON DELETEON UPDATE 子句 (如同目前子資料表定義) 等同於指定 RESTRICT 選項,這會拒絕影響父資料表中具有相符資料列的鍵值的操作。

為了演示 ON DELETEON UPDATE 參照動作,請刪除子資料表並重新建立它,以包含具有 CASCADE 選項的 ON UPDATEON 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 節,「外來鍵限制」