2012-10-19 223 views
12

這似乎是一個常見錯誤,但對於我的生活,我無法弄清楚這一點。MySQL - 無法添加或更新子行:外鍵約束失敗

我在MySQL中有一組InnoDB用戶表,它們通過外鍵連接在一起;父表user表和一組存儲電子郵件地址,動作等的子表。這些都通過外鍵uid連接到父表user表,所有父鍵和子鍵都是int(10)

所有的子表都有一個uid值,其外鍵約束指向user.uid,並且設置爲ON DELETE CASCADEON UPDATE CASCADE

當我從user中刪除一個用戶時,所有的子約束條目都被刪除。然而,當我嘗試更新user.uid值,它會導致下面的錯誤,而不是級聯uid變化的子表:

#1452 - Cannot add or update a child row: a foreign key constraint fails (`accounts`.`user_email`, CONSTRAINT `user_email_ibfk_2` FOREIGN KEY (`uid`) REFERENCES `user` (`uid`) ON DELETE CASCADE ON UPDATE CASCADE) 

我有一種感覺,我必須在這裏失去了一些東西明顯。使用user_email刪除密鑰約束並嘗試更新user中的值會導致相同的錯誤,但對於下一個字母表user子表,因此我不相信這是表特定的錯誤。

編輯:

在結果中添加從SHOW ENGINE INNODB STATUS

------------------------ 
LATEST FOREIGN KEY ERROR 
------------------------ 
121018 22:35:41 Transaction: 
TRANSACTION 0 5564387, ACTIVE 0 sec, process no 1619, OS thread id 2957499248 updating or deleting, thread declared inside InnoDB 499 
mysql tables in use 1, locked 1 
17 lock struct(s), heap size 2496, 9 row lock(s), undo log entries 2 
MySQL thread id 3435659, query id 24068634 localhost root Updating 
UPDATE `accounts`.`user` SET `uid` = '1' WHERE `user`.`uid` = 306 
Foreign key constraint fails for table `accounts`.`user_email`: 
, 
    CONSTRAINT `user_email_ibfk_2` FOREIGN KEY (`uid`) REFERENCES `user` (`uid`) ON DELETE CASCADE ON UPDATE CASCADE 
Trying to add in child table, in index `uid` tuple: 
DATA TUPLE: 2 fields; 
... 
A bunch of hex code 

But in parent table `accounts`.`user`, in index `PRIMARY`, 
the closest match we can find is record: 
... 
A bunch of hex code 
+0

'SHOW ENGINE INNODB STATUS' –

+0

投票將其移至dba。 –

回答

1

在一個不相關的任務上,我最近提出了我們的MySQL數據庫MySQL Workbench,當查看上表的關係時,我注意到'重複'和/或虛假關係,我以前不知何故錯過了它們沒有出現在PHPMyAdmin FWIW中)。消除這些額外的關係可以立即解決問題。

8

因爲你沒有給表定義,這是很難猜測。但它看起來像你試圖修改子表中的外鍵。 AFAIK,這是非法的,你可以修改它從父,但不是子表。

考慮這個例子:

CREATE TABLE parent (
    parent_id INT NOT NULL, 
    parent_data int, 

    PRIMARY KEY (parent_id) 
) ENGINE=INNODB; 

CREATE TABLE child1 (
    child1_id INT, 
    child1_data INT, 
    fk_parent_id INT, 

    INDEX par_ind1 (fk_parent_id), 

    FOREIGN KEY (fk_parent_id) 
    REFERENCES parent(parent_id) 
    ON DELETE CASCADE 
    ON UPDATE CASCADE 
) ENGINE=INNODB; 

CREATE TABLE child2 (
    child2_id INT, 
    child2_data INT, 
    fk_parent_id INT, 

    INDEX par_ind2 (fk_parent_id), 

    FOREIGN KEY (fk_parent_id) 
    REFERENCES parent(parent_id) 
    ON DELETE CASCADE 
    ON UPDATE CASCADE 
) ENGINE=INNODB; 

INSERT INTO parent 
    (parent_id, parent_data) 
    VALUES 
    (1, 11), 
    (2, 12); 

INSERT INTO child1 
    (child1_id, child1_data, fk_parent_id) 
    VALUES 
    (101, 1001, 1), 
    (102, 1002, 1), 
    (103, 1003, 1), 
    (104, 1004, 2), 
    (105, 1005, 2); 

INSERT INTO child2 
    (child2_id, child2_data, fk_parent_id) 
    VALUES 
    (106, 1006, 1), 
    (107, 1007, 1), 
    (108, 1008, 1), 
    (109, 1009, 2), 
    (110, 1010, 2); 

那麼這是允許的:

UPDATE parent 
    SET parent_id = 3 WHERE parent_id = 2; 

SELECT * FROM parent; 
SELECT * FROM child1; 
SELECT * FROM child2; 

但這不是,因爲它從子表修改父FK:

UPDATE child1 
    SET fk_parent_id = 4 WHERE fk_parent_id = 1; 

它會得到與您的錯誤非常相似的錯誤:

Cannot add or update a child row: a foreign key constraint fails (`db_2_b43a7`.`child1`, CONSTRAINT `child1_ibfk_1` FOREIGN KEY (`fk_parent_id`) REFERENCES `parent` (`parent_id`) ON DELETE CASCADE ON UPDATE CASCADE): 
+0

謝謝。我正在更新父表 - 查看我發佈的轉儲中的查詢:'UPDATE \'accounts \'。\'user''SET \'uid \'='1'WHERE \'user \'。\'uid \ '= 306'。 'user'是父表,並觸發這個錯誤。 –

+0

你能發佈更多關於你的模式的信息嗎?或者修改上面的例子,以便得到相同的錯誤? – walrii

4

我在創建表上的外部約束時遇到了同樣的問題。出現這個問題的簡單方法是先備份父表和子表,然後截斷子表並再次嘗試創建關係。希望這會解決問題。

-1

希望這將有助於任何人在將CSV數據導入到相關表格時出現相同錯誤。在我的情況下,父表是確定的,但是在將數據導入包含外鍵的子表中時出現錯誤。在臨時刪除子表上的foregn鍵約束之後,我設法導入了這些數據,並驚訝地發現FK列中值爲0的一些值(顯然這是由於父表沒有這些值在其PK欄中)。原因是,我的CSV列中的數據在FK列之前包含逗號(我用作字段分隔符)。更改我的CSV文件的分隔符解決了問題。

9

我解決了我加入以下代碼,SQL代碼的開始「外鍵約束失敗」的問題(這是對進口值表)

SET @[email protected]@CHARACTER_SET_CLIENT; 
SET @[email protected]@CHARACTER_SET_RESULTS; 
SET @[email protected]@COLLATION_CONNECTION; 
SET NAMES utf8; 
SET @[email protected]@UNIQUE_CHECKS, UNIQUE_CHECKS=0; 
SET @[email protected]@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0; 
SET @[email protected]@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO'; 
SET @[email protected]@SQL_NOTES, SQL_NOTES=0; 

然後將此代碼添加到文件

SET [email protected]_SQL_MODE; 
SET [email protected]_FOREIGN_KEY_CHECKS; 
SET [email protected]_UNIQUE_CHECKS; 
SET [email protected]_CHARACTER_SET_CLIENT; 
SET [email protected]_CHARACTER_SET_RESULTS; 
SET [email protected]_COLLATION_CONNECTION; 
SET [email protected]_SQL_NOTES; 
+0

精美地工作 –

+0

它的工作原理!謝謝 – tiveor

+0

LIFE SAVER MAN,THANKS –

0

這樣的更新的錯誤可能是由字符集和校對規則的不同而引起的末尾,以便確保它們是兩個表的相同。

相關問題