【发布时间】:2021-06-22 01:34:41
【问题描述】:
我有一个表products,其架构如下:
CREATE TABLE `products` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`user_id` bigint unsigned NOT NULL,
`article_id` bigint unsigned NOT NULL,
`price_cents` int unsigned NOT NULL,
`quantity` smallint NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `idx_products_unique` (`user_id`,`article_id`,`price_cents`),
KEY `fk_products_article` (`article_id`),
CONSTRAINT `fk_products_article` FOREIGN KEY (`article_id`) REFERENCES `articles` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `fk_products_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB
现在我可以用这个查询做 INSERT:
INSERT INTO `products` (`user_id`,`article_id`,`price_cents`,`quantity`)
VALUES (1,1,200,1)
ON DUPLICATE KEY UPDATE `price_cents`=VALUES(`price_cents`),`quantity`=quantity+VALUES(`quantity`)
所以现在我有 1 个产品 (ID 1),数量为 1,价格为 200。 现在我插入另外 2 个产品:
INSERT INTO `products` (`user_id`,`article_id`,`price_cents`,`quantity`)
VALUES (1,1,200,1),(1,1,199,1)
ON DUPLICATE KEY UPDATE `price_cents`=VALUES(`price_cents`),`quantity`=quantity+VALUES(`quantity`)
现在我有 2 件产品,一件 (ID 1) 的数量为 2,价格为 200,另一件 (ID 2) 的数量为 1,价格为 199。
很好。
现在问题来了:我想更新价格为 199 的产品并将新价格设置为 200。我要做的是:
INSERT INTO `products` (`id`,`user_id`,`article_id`,`price_cents`,`quantity`)
VALUES (2,1,1,200,1)
ON DUPLICATE KEY UPDATE `price_cents`=VALUES(`price_cents`),`quantity`=quantity+VALUES(`quantity`)
而我想要的是ID为1、价格为200、数量为3的单一产品,但我得到Number:0x426, Message: "Duplicate entry '1-1-200' for key 'products.idx_products_unique',因为MySQL不会删除ID为2的产品。
有没有办法在 MySQL 中实现这一点(请记住,我想批量执行这些操作)?
【问题讨论】:
-
问题是重复键在另一条记录中,所以你不能用一条sql语句来做到这一点。检测到dupkucate key错误后,需要删除价格为199的记录,更新价格为200行的数量。
-
您有 2 个唯一约束 - 主键和
idx_products_unique。如果由于一个约束违反而触发更新,并且更新的值导致另一个约束违反(您的选择),则查询失败。 -
将价格作为唯一键的一部分似乎不正常。这意味着您持有 相同 价格不同的产品??
-
@RickJames 准确
-
您提到“批量”做事。请详细说明和/或举例。另外,批次中可能有多少个项目?我认为可能有一种方法可以在 2 个 SQL 语句中批处理任意数量的项目(一个用于更新,一个用于“合并”),但我没有仔细考虑细节。 (没有自动方法可以在单个语句中完成。)