2014-09-04 129 views
2

如何在外鍵僅引用複合主鍵的一部分時從父表中刪除?mysql外鍵僅引用複合主鍵的一部分

我使用的MySQL 5.6.2

我有具有主鍵項目(A,B)和料品供應商具有主鍵itemsup一個項目表(A,X,Y)。我有給喜歡(A)項基準= itemsup(A)
當我從項目中刪除(父)表我得到錯誤:1451 - 不能刪除或更新父行,外鍵約束失敗

我的表格結構如下。

CREATE TABLE IF NOT EXISTS ITEM (/* parent */ 
    ITEMID INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'ITEM ID', 
    MCA ENUM('A','C','M','X') NOT NULL , 
    ITEMNAME VARCHAR(100) NOT NULL COMMENT 'NAME OF ITEM', 
    PRIMARY KEY (ITEMID, MCA) 
) 
ENGINE = InnoDB; 

CREATE TABLE IF NOT EXISTS ITEMSUP (/* child */ 
    ITEMID INT UNSIGNED NOT NULL, 
    SUPID INT UNSIGNED NOT NULL, 
    MCA ENUM('A','C','M','X') NOT NULL , 
    PRIMARY KEY (ITEMID, SUPID, MCA), 
    CONSTRAINT FK_ITEMSUP_ITEM1 
    FOREIGN KEY (ITEMID) 
    REFERENCES ITEM (ITEMID) 
    ON DELETE NO ACTION 
    ON UPDATE CASCADE 
) 
ENGINE = InnoDB; 

INSERT INTO ITEM (ITEMID, MCA, ITEMNAME) VALUES (1,'A', 'ONE A'); 
INSERT INTO ITEM (ITEMID, MCA, ITEMNAME) VALUES (1,'M', 'ONE M'); 
INSERT INTO ITEMSUP(ITEMID, SUPID, MCA) VALUES(1,1,'X'); 
/* below is not working */ 
DELETE FROM ITEM WHERE ITEMID = 1 AND MCA ='A'; 

http://sqlfiddle.com/#!9/fb961/1

我已經找到一個解決方案,但不知道它的對錯。

SET FOREIGN_KEY_CHECKS = 0; 
DELETE FROM ITEM WHERE ITEMID =1 AND MCA ='A'; 
SET FOREIGN_KEY_CHECKS = 1; 
+0

爲什麼您的FK(ITEMID)而不是(ITEMID,MCA)? – philipxy 2014-09-21 21:07:32

回答

0

爲什麼錯誤信息?

在標準SQL中,被引用的列集必須聲明爲UNIQUE NON NULL或PRIMARY KEY。

不幸的是,MySQL允許引用的集合不是唯一的非null。從the MySQL manual re Using FOREIGN KEY Constraints

然而,該系統並不強制引用 列是唯一的或者是NOT NULL聲明的要求。外鍵 對包含NULL值的非唯一鍵或鍵的引用不是 ,對於諸如UPDATE或DELETE CASCADE之類的操作已經定義好了。建議您使用僅引用UNIQUE(包括 PRIMARY)和NOT NULL鍵的外鍵的爲 。

特別from the MySQL manual re InnoDB and FOREIGN KEY Constraints

如果有父表幾行具有相同 引用的密鑰值,InnoDB的作用外鍵的支票,如果用相同的 其他父行鍵值不存在。例如, 如果您已定義RESTRICT類型約束,並且存在包含多個父行的子行,則InnoDB不允許刪除這些父行中的任何一個 。

這就是爲什麼你會得到錯誤。也就是說,ITEM中的同一行有多個ITEMID行。

適應你的設計

在關係和標準SQL的概念來說的,一次只能有外鍵(ITEMID)參考項目(ITEMID)在ITEMSUP如果ITEMID是項獨特&不爲空。由於ITEMID並不意味着你在ITEM中是唯一的,所以你不可能想要一個FOREIGN KEY。 (非正式地,ITEMID不是ITEM的「關鍵」,因此它不能成爲ITEMSUP中的外部「關鍵」。)

要使每個ITEMSUP ITEMID成爲ITEM ITEMID的值,請將ITEMID PRIMARY KEY新表,並從ITEMID和ITEMSUP(而不是當前的ITEMSUP外鍵)向它提供FOREIGN KEY。

提高您的設計

也許「X」是一種「空」表示沒有MCA的,並有不必須是匹配的MCS。並且/或者當ITEMSUP ITEMID的MCA不是'X'和/或是'X'時,它必須匹配它的ITEM MCA。也許你只希望ITEM中的每個ITEMID都有一個MCA,在這種情況下將ITEM更改爲ITEMID PRIMARY KEY和MCA NOT NULL UNIQUE。也許項目可以有多個ITEMID-MCA對,但ITEMSUP只能有那些的,在這種情況下有不同的ITEMSUP外鍵:

FOREIGN KEY (ITEMID,MCA) REFERENCES ITEM (ITEMID,MCA) 

但這將通過您的SQLFiddle侵犯:

INSERT INTO ITEMSUP(ITEMID, SUPID, MCA) VALUES(1,1,'X'); 

因爲ITEM中沒有相應的子行(1,'X')。

如果任何「可能」是真的,那麼你沒有正確描述你的表上的約束。除非您確切確定您需要的約束條件,否則我們無法就您的設計應該如何正確提供建議。