三大前置條件
- 兩表皆使用 InnoDB 引擎。
- 外鍵欄位必須建立 索引 (INDEX)。
- 外鍵欄位與參照欄位 資料型別、長度、字元集完全一致。
範例:書籍借閱系統
-- 父表:書籍
CREATE TABLE IF NOT EXISTS `books` (
`book_id` SMALLINT(6) NOT NULL AUTO_INCREMENT COMMENT '書籍編號',
`book_name` CHAR(20) NOT NULL COMMENT '書名',
`book_borrower` CHAR(6) DEFAULT NULL COMMENT '借閱者',
PRIMARY KEY (`book_id`),
INDEX (`book_borrower`) -- 外鍵欄位必須有索引
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- 子表:成員
CREATE TABLE IF NOT EXISTS `parts` (
`part_id` SMALLINT(6) NOT NULL COMMENT '成員編號',
`part_name` VARCHAR(6) NOT NULL COMMENT '成員名',
PRIMARY KEY (`part_id`),
FOREIGN KEY (`part_name`) REFERENCES `books`(`book_borrower`)
ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
關鍵點解析
ON DELETE CASCADE:刪除書籍記錄時,自動刪除對應借閱記錄。
ON UPDATE CASCADE:更新書籍借閱者欄位時,同步更新成員表。
- 子表外鍵欄位 `part_name` (VARCHAR) 對應父表 `book_borrower` (CHAR),型別兼容(皆為字串)。
- 建立外鍵後,MySQL 會自動在子表外鍵欄位建立索引(若尚無)。
常見錯誤與排查
| 錯誤代碼 | 原因 | 解決 |
| 1005 (errno: 150) | 型別不符 / 父表欄位無索引 / 引擎非 InnoDB | 檢查三大前置條件 |
| 1216 | 新增子記錄時父記錄不存在 | 先插入父表或暫時關閉外鍵檢查 |
| 1217 | 刪除父記錄時存在子記錄 | 先刪子記錄或用 CASCADE |
實務建議
- 高併發寫入系統慎用外鍵(鎖開銷大),改由應用層維護參考完整性。
- 資料倉庫/報表系統建議保留外鍵,確保資料品質。
- 使用 `SET FOREIGN_KEY_CHECKS=0;` 可暫時關閉檢查(大量匯入時)。