[英]MySQL won't allow update despite ON UPDATE CASCADE in foreign key
[英]mysql cascade won't work when trying to update primary key that is referenced by 2 columns in a different table as foreign keys
我在更新數據庫時遇到問題。
這是我的結構:
我有一個名為''users'的表:
CREATE TABLE `users` (
`username` varchar(45) NOT NULL,
PRIMARY KEY (`username`)
)
INSERT INTO `users` VALUES ('alice'),('bob'),('john');
我有一個名為''orders'的表:
CREATE TABLE `orders` (
`user1` varchar(45) NOT NULL,
`user2` varchar(45) NOT NULL,
`date` datetime DEFAULT NULL,
PRIMARY KEY (`user1`,`user2`),
KEY `user2_idx` (`user2`),
CONSTRAINT `user1` FOREIGN KEY (`user1`) REFERENCES `users` (`username`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `user2` FOREIGN KEY (`user2`) REFERENCES `users` (`username`) ON DELETE CASCADE ON UPDATE CASCADE
)
INSERT INTO `orders` VALUES ('alice','bob',NULL),('alice','john',NULL),('bob','bob',NULL);
這意味着訂單由2個用戶組成,即“訂單”表的記錄由引用“用戶”表的2個外鍵組合而成。
我遇到的問題是我現在需要更改用戶的用戶名。
正如上面的代碼指定我有:3個用戶:'alice','bob'和'john'3個命令:('alice','bob'),('alice','john'),('bob', “鮑勃”)
如果我嘗試編輯'alice'或'john'用戶名,那么操作將成功,級聯將相應地更改所有訂單。
但如果我嘗試將'bob'用戶名更改為其他內容我將收到這個可怕的錯誤消息,我無法理解為什么:
Operation failed: There was an error while applying the SQL script to the database.
Executing:
UPDATE `test`.`users` SET `username`='bobd' WHERE `username`='bob';
ERROR 1452: 1452: Cannot add or update a child row: a foreign key constraint fails (`test`.`orders`, CONSTRAINT `user2` FOREIGN KEY (`user2`) REFERENCES `users` (`username`) ON DELETE CASCADE ON UPDATE CASCADE)
SQL Statement:
UPDATE `test`.`users` SET `username`='bobd' WHERE `username`='bob'
您輸入bob,bob是個問題,因為它有兩個鍵(主鍵,外鍵)和兩個與之關聯的約束(user1,user2)。 它們都引用相同的字段users.username。 這嚴重混淆了數據庫軟件並且是糟糕的設計。
最簡單的解決方案是刪除約束,更新表並重新建立約束。
在您的用戶表中,您應該使用ID,ID和ID上的密鑰。 然后在訂單表中,使用ID,ID。 然后,您可以在一個表中更新名稱而不會出現問題。
為了幫助進行數據庫設計,您應該閱讀第三范式。
我認為這個條款已經咬了你的屁股:
在兩個表之間,不要定義幾個
ON UPDATE CASCADE
子句,這些子句作用於父表或子表中的同一列。
如您所見,服務器為級聯更新的每個約束發出單獨的UPDATE
語句。 但是,如果有兩個列受影響,那么這兩個語句都不能自行生成有效行!
這里可能的解決方案是使用用戶ID作為其永不改變而不是任何輔助信息的唯一身份。
事實上,在任何事情都可能隨時間變化的情況下,這是經過時間驗證的最佳實踐: 自然鍵在SQL Server中提供的性能是否比代理整數鍵更高或更低? 概述了利弊。
我在使用JPA / Hibernate時遇到了這個問題。 DDL更新(hibernate.hbm2ddl.auto = update)創建了重復的外鍵約束。 我刪除了原始約束,並保留了生成的約束。 這解決了我的問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.