我在更新数据库时遇到问题。
这是我的结构:
我有 1 个名为“users”的表:
CREATE TABLE `users` (
`username` varchar(45) NOT NULL,
PRIMARY KEY (`username`)
)
INSERT INTO `users` VALUES ('alice'),('bob'),('john');
我有 1 个名为:“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 个用户组成,即“orders”表的一条记录由引用“users”表的 2 个外键组合而成。
我遇到的问题是我现在需要更改用户的用户名。
如上面的代码所示,我有: 3 个用户:“alice”、“bob”和“john” 3 个订单:('alice','bob'), ('alice','john'), ('bob','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'
最佳答案
我认为这个条款已经让你痛不欲生了:
Using FOREIGN KEY Constraints :
Between two tables, do not define several
ON UPDATE CASCADE
clauses that act on the same column in the parent table or in the child table.
如您所见,服务器为级联更新的每个约束发出单独的 UPDATE
语句。但是,如果有两列受到影响,则这两个语句都无法自行生成有效行!
这里的一个可能的解决方案是使用用户 ID 作为他们的唯一身份,该身份永远不会改变,而不是任何辅助信息。
事实上,在任何事情都会随时间发生变化的情况下,这是耗时证明的最佳实践:Do natural keys provide higher or lower performance in SQL Server than surrogate integer keys?概述了优点和缺点。
关于当尝试更新由不同表中的 2 列作为外键引用的主键时,mysql 级联将不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28653262/