記一個Mysql外鍵約束設計缺陷
背景資訊
最近在做項目的資料庫遷移,從Oracle到Mysql,一個外鍵約束在Oracle運行正常,在mysql報異常。(因為才接手沒幾天,對業務和架構不熟,在處理問題時花了很多時間。)
[2018-08-01 13:34:19] [23000][1452] Cannot add or update a child row: a foreign key constraint fails (`bov`.`PRO_SITES_BRANDREQUEST`, CONSTRAINT `AA` FOREIGN KEY (`ID`) REFERENCES `PRO_SITES_SETUPREQUEST` (`ID`) ON DELETE CASCADE)
Oracle的DDL
drop table Models;CREATE TABLE Models( ModelID number(6) PRIMARY KEY, Name VARCHAR(40));drop table Orders;CREATE TABLE Orders( ModelID number(8) PRIMARY KEY, Description VARCHAR(40), FOREIGN KEY (ModelID) REFERENCES Models (ModelID) ON DELETE cascade);insert into Models(ModelID, Name) values (1,'model');insert into Orders(ModelID,Description) values (1,'order');
select * from Models;1 modelselect * from Orders;1 order
Mysql的DDL
drop table Models;CREATE TABLE Models( ModelID decimal(6,0) PRIMARY KEY, Name VARCHAR(40));drop table Orders;CREATE TABLE Orders( ModelID decimal(8,0) PRIMARY KEY, Description VARCHAR(40), FOREIGN KEY (ModelID) REFERENCES Models (ModelID) ON DELETE cascade);insert into Models(ModelID, Name) values (1,'model');insert into Orders(ModelID,Description) values (1,'order');
在執行最後一句時,報異常
[2018-08-01 14:06:16] [23000][1452] Cannot add or update a child row: a foreign key constraint fails (`bov`.`Orders`, CONSTRAINT `Orders_ibfk_1` FOREIGN KEY (`ModelID`) REFERENCES `Models` (`ModelID`) ON DELETE CASCADE)
原因:Models的ModelID是decimal(6,0),而Orders的ModelID是decimal(8,0),兩個通過外鍵相連。因為類型不一致,mysql就不會認為其一定不等,而oracle可以做到不同類型的相容判等。
解決方案
drop table Orders;CREATE TABLE Orders( ModelID decimal(6,0) PRIMARY KEY, Description VARCHAR(40), FOREIGN KEY (ModelID) REFERENCES Models (ModelID) ON DELETE cascade);insert into Orders(ModelID,Description) values (1,'order');
select * from Models;1 modelselect * from Orders;1 order
總結
Mysql的外鍵約束設計有缺陷,如果不同單位的欄位一定不同,應在添加FOREIGN KEY就報異常,而不是模稜兩可的因為類型不同,但實際數值相等,其判斷為不等於。
資料庫表維護的時候,不同table中,意義相同的column,類型一定要保持一致。