簡體   English   中英

嘗試更新由另一個表中的2列作為外鍵引用的主鍵時,mysql級聯將無法工作

[英]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。 然后,您可以在一個表中更新名稱而不會出現問題。

為了幫助進行數據庫設計,您應該閱讀第三范式。

我認為這個條款已經咬了你的屁股:

使用FOREIGN KEY約束

在兩個表之間,不要定義幾個ON UPDATE CASCADE子句,這些子句作用於父表或子表中的同一列。

如您所見,服務器為級聯更新的每個約束發出單獨的UPDATE語句。 但是,如果有兩個列受影響,那么這兩個語句都不能自行生成有效行!

這里可能的解決方案是使用用戶ID作為其永不改變而不是任何輔助信息的唯一身份。
事實上,在任何事情都可能隨時間變化的情況下,這是經過時間驗證的最佳實踐: 自然鍵在SQL Server中提供的性能是否比代理整數鍵更高或更低? 概述了利弊。

我在使用JPA / Hibernate時遇到了這個問題。 DDL更新(hibernate.hbm2ddl.auto = update)創建了重復的外鍵約束。 我刪除了原始約束,並保留了生成的約束。 這解決了我的問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM