MySQL 中的外鍵


表和表之間可存在引用關系,這在抽象數據到表時,是很常見的。這種聯系是通過在表中創建外鍵(foreign key)來實現的。

比如一個訂單,可能關聯用戶表和產品表,以此來記錄買了什么產品

約定兩個概念:

父表:被引用的表。
從表:表中有相應的外鍵引用父表中的字段。

示例:

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)
ON DELETE CASCADE
) ENGINE=INNODB;

這里 parent 為父表,child 為從表。

外鍵關聯表的同步操作

當表和表之間建立起合適的關聯后, INSERTUPDATE 操作會自動檢查所插入的記錄中指定的外鍵在相應表中是否存在;

建立外鍵時,可指定 ON UPDATE <action>ON DELETE <action> 子語句來指定發生 UPDATEDELETE 操作時,外鍵關聯表中數據該如何處理。MySQL 中支持五種處理(action):

  • CASCADE:更新或刪除父表記錄時,自動更新或刪除從表中匹配的記錄。實際使用時注意不要在父表或從表中對同一列重復定義 ON UPDATE CASCADE。CASCADE 類型的操作不會激活觸發器 (triggers)。
  • SET NULL:更新或刪除父表中記錄時,將從表中匹配的記錄其外鍵設置為 NULL,前提時從表中該外鍵沒有指定為 NOT NULL
  • RESTRICT:默認為該項。禁用父表中的更新或刪除操作,這與缺省 ON DELETEON UPDATE 子語句效果一樣。
  • NO ACTION:來自 SQL 標准中定義的一種操作,與上面 RESTRICT 等效。一些數據庫支持延遲檢查(deferred check), NO ACTION 便是這種可延遲檢查的操作。在 MySQL 中,外鍵的檢查是及時的,所以 NO ACTIONRESTRICT 完全等效。
  • SET DEFAULT: MySQL 能夠解析識別該動作,但 InnoDBNDB 引擎不支持。

添加外鍵

創建外鍵的語法
[CONSTRAINT [symbol]] FOREIGN KEY
    [index_name] (col_name, ...)
    REFERENCES tbl_name (col_name,...)
    [ON DELETE reference_option]
    [ON UPDATE reference_option]

reference_option:
RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT

文章開頭提到的訂單表示例:

CREATE TABLE product (
    category INT NOT NULL, id INT NOT NULL,
    price DECIMAL,
    PRIMARY KEY(category, id)
)   ENGINE=INNODB;

CREATE TABLE customer (
id INT NOT NULL,
PRIMARY KEY (id)
) ENGINE=INNODB;

CREATE TABLE product_order (
no INT NOT NULL AUTO_INCREMENT,
product_category INT NOT NULL,
product_id INT NOT NULL,
customer_id INT NOT NULL,

<span class="pl-k">PRIMARY KEY</span>(no),
INDEX (product_category, product_id),
INDEX (customer_id),

<span class="pl-k">FOREIGN KEY</span> (product_category, product_id)
  <span class="pl-k">REFERENCES</span> product(category, id)
  <span class="pl-k">ON</span> <span class="pl-k">UPDATE</span> CASCADE <span class="pl-k">ON DELETE</span> RESTRICT,

<span class="pl-k">FOREIGN KEY</span> (customer_id)
  <span class="pl-k">REFERENCES</span> customer(id)

) ENGINE=INNODB;

所以這個關系里有兩個父表 customerproduct,一個從表 product_order

對現有表添加外鍵可使用如下的語句:

ALTER TABLE tbl_name
    ADD [CONSTRAINT [symbol]] FOREIGN KEY
    [index_name] (col_name, ...)
    REFERENCES tbl_name (col_name,...)
    [ON DELETE reference_option]
    [ON UPDATE reference_option]

創建外鍵時可指定 [symbol],即給外鍵取一個名稱,這樣在其他操作時可以引用,比如刪除外鍵時。

刪除外鍵

同樣是通過 ALTER TABLE 語句來完成。

ALTER TABLE tbl_name DROP FOREIGN KEY fk_symbol;

刪除外鍵時,如果該外鍵在創建時取了名稱,名通過該名稱來刪除,如果沒有,則需要先查詢 MySQL 在創建該外鍵時自動生成的名稱 fk_symbol 是什么。可通過 SHOW CREATE TABLE <table_name> 來完成查詢。譬如:

mysql> SHOW CREATE TABLE dept_manager\G
*************************** 1. row ***************************
       Table: dept_manager
Create Table: CREATE TABLE `dept_manager` (
  `emp_no` int(11) NOT NULL,
  `dept_no` char(4) COLLATE utf8mb4_general_ci NOT NULL,
  `from_date` date NOT NULL,
  `to_date` date NOT NULL,
  PRIMARY KEY (`emp_no`,`dept_no`),
  KEY `dept_no` (`dept_no`),
  CONSTRAINT `dept_manager_ibfk_1` FOREIGN KEY (`emp_no`) REFERENCES `employees` (`emp_no`) ON DELETE CASCADE,
  CONSTRAINT `dept_manager_ibfk_2` FOREIGN KEY (`dept_no`) REFERENCES `departments` (`dept_no`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci
1 row in set (0.00 sec)

相關資源


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM