首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 外鍵創建失敗 Error 150 完整排查清單:9 大常見原因與解決方案

     編輯:MySQL 資料庫相關知識

MySQL 報錯 ERROR 1005 (HY000): Can't create table ... (errno: 150) 是外鍵創建失敗的通用提示,實際原因隱藏在細節中。本文彙總 9 大高發原因,按概率排序,附帶排查 SQL 與修復方案。

原因排查清單(按高發頻率排序)

1. 字段類型/長度/符號位不完全一致 ⭐⭐⭐⭐⭐

現象:父表 INT(10),子表 INT(11);或一個 SIGNED 一個 UNSIGNED。

排查:

SHOW CREATE TABLE parent_table;
SHOW CREATE TABLE child_table;
-- 重點對比:類型、長度、UNSIGNED/SIGNED

修復:ALTER TABLE child_table MODIFY col INT(10) UNSIGNED; 保持完全一致。

2. 父表關聯列無索引/非主鍵 ⭐⭐⭐⭐

規則:被引用列必須是主鍵,或有唯一索引/普通索引(InnoDB 要求)。

修復:

ALTER TABLE parent_table ADD INDEX idx_fk_col (fk_col);
-- 或
ALTER TABLE parent_table ADD PRIMARY KEY (fk_col);

3. 外鍵名稱衝突 ⭐⭐⭐

現象:同一數據庫下外鍵名稱重複(即使跨表)。

排查:

SELECT CONSTRAINT_NAME FROM information_schema.TABLE_CONSTRAINTS
WHERE CONSTRAINT_TYPE = 'FOREIGN KEY' AND TABLE_SCHEMA = 'your_db';

修復:顯式指定唯一名稱 CONSTRAINT fk_unique_name FOREIGN KEY ...

4. 表引擎不支持外鍵 ⭐⭐⭐

現象:任一表為 MyISAM(不支持外鍵約束)。

排查:

SHOW TABLE STATUS WHERE Name IN ('parent', 'child');
-- 檢查 Engine 列

修復:

ALTER TABLE parent_table ENGINE=InnoDB;
ALTER TABLE child_table ENGINE=InnoDB;

5. ON DELETE SET NULL 但列定義 NOT NULL ⭐⭐

現象:外鍵定義 ON DELETE SET NULL,但子表關聯列 NOT NULL。

修復:

-- 方案一:允許 NULL
ALTER TABLE child_table MODIFY fk_col INT NULL;
-- 方案二:改為 CASCADE/RESTRICT
ALTER TABLE child_table DROP FOREIGN KEY fk_name;
ALTER TABLE child_table ADD CONSTRAINT fk_name FOREIGN KEY ... ON DELETE CASCADE;

6. 字符集/排序規則不一致 ⭐⭐

現象:表級或列級 CHARSET/COLLATE 不同(如 utf8 vs utf8mb4,或 _general_ci vs _unicode_ci)。

排查:

SHOW CREATE TABLE parent_table;
SHOW CREATE TABLE child_table;
-- 對比 DEFAULT CHARSET、列級 CHARSET

修復:統一為 utf8mb4 + utf8mb4_unicode_ci。

7. 外鍵列設置了 DEFAULT 值 ⭐

現象:如 fk_col INT DEFAULT 0,MySQL 某版本禁止外鍵列有默認值。

修復:ALTER TABLE child_table ALTER fk_col DROP DEFAULT;

8. 關聯列是組合索引非首列 ⭐

現象:父表 INDEX idx_a_b (a, b),外鍵引用 b 列。

規則:被引用列必須是索引的最左前綴。

修復:ALTER TABLE parent_table ADD INDEX idx_b (b);

9. ALTER TABLE 語法錯誤 ⭐

現象:引號、逗號、關鍵字拼寫錯誤。

修復:參考官方文檔標準語法:

ALTER TABLE child_table
ADD CONSTRAINT fk_name
FOREIGN KEY (fk_col) REFERENCES parent_table (pk_col)
ON DELETE CASCADE ON UPDATE CASCADE;

一鍵診斷腳本

SELECT 
  tc.CONSTRAINT_NAME,
  tc.TABLE_NAME AS child_table,
  kcu.COLUMN_NAME AS child_column,
  tc.REFERENCED_TABLE_NAME AS parent_table,
  kcu.REFERENCED_COLUMN_NAME AS parent_column,
  rc.UPDATE_RULE,
  rc.DELETE_RULE
FROM information_schema.TABLE_CONSTRAINTS tc
JOIN information_schema.KEY_COLUMN_USAGE kcu
  ON tc.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME
JOIN information_schema.REFERENTIAL_CONSTRAINTS rc
  ON tc.CONSTRAINT_NAME = rc.CONSTRAINT_NAME
WHERE tc.CONSTRAINT_TYPE = 'FOREIGN KEY'
  AND tc.TABLE_SCHEMA = 'your_db';

工具建議

複雜 ER 關係建議用建模工具(MySQL Workbench、PowerDesigner、MyEclipse DDL 生成)正向設計,避免手寫 DDL 易漏細節。

核心口訣:類型長度符號一致、父列必有索引、引擎必須 InnoDB、字符集統一、名稱全局唯一。逐項核對 99% 可解。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved