mysql - mysql ON DUPLICATE KEY UPDATE 的替代解决方案
问题描述
我有两张MySql
桌子。一通电话item
,一通电话price
。
表数据item
如下所示:
+---------+-----------+-----------+-------+
| item_id | item_code | item_name | price |
+---------+-----------+-----------+-------+
| 1 | 02 | item A | 10.00 |
| 2 | 03 | item B | 20.00 |
| 3 | 04 | item C | 30.00 |
+---------+-----------+-----------+-------+
价格表结构如下:
CREATE TABLE `price` (
`price_id` int(11) NOT NULL AUTO_INCREMENT,
`price` decimal(16,2) NOT NULL,
`valid_from` date DEFAULT NULL,
`valid_until` date DEFAULT NULL,
`item_id` int(11) NOT NULL,
PRIMARY KEY (`price_id`),
KEY `fk_item_price_item1_idx` (`item_id`),
CONSTRAINT `fk_item_price_item1` FOREIGN KEY (`item_id`) REFERENCES `item` (`item_id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8
我真正需要的是从item
表中获取数据并将其插入或更新到 price
表中。
如果根据item_id,item表的价格不等于item表的价格,则需要更新price表中与该item_id相关的数据。(此处valid_until
字段已更新。)然后应将新价格插入此价格表中。
我知道这可以通过ON DUPLICATE KEY UPDATE
查询来完成。但我不能item_id / price
对price
表中的文件使用唯一索引或约束。因此,我将使用两个单独的查询进行更新和插入,如下所示。
UPDATE item i
JOIN price p ON i.item_id = p.item_id
AND p.price <> i.price
AND CURDATE () BETWEEN p.valid_from AND COALESCE (p.valid_until, '9999-12-31')
SET p.valid_until = CURDATE () - INTERVAL 1 DAY
INSERT IGNORE INTO `price` (`price`,`item_id`, `valid_from`)
SELECT DISTINCT `i`.`price`, `i`.`item_id`, CURDATE()
FROM `item` `i`
INNER JOIN `price` `p` ON `p`.`item_id` = `i`.`item_id`;
更新查询工作没有任何问题。但是插入查询不能正常工作。这意味着即使价格相同,也会插入一个新行。
希望有人可以帮助我。
解决方案
编写SELECT
查询以查找查询item
中不匹配的行UPDATE
,然后插入它们。
INSERT INTO price (`price`,`item_id`, `valid_from`)
SELECT DISTINCT i.price, i.item_id, CURDATE()
FROM item AS i
LEFT JOIN price AS p ON i.item_id = p.item_id AND CURDATE () BETWEEN p.valid_from AND COALESCE (p.valid_until, '9999-12-31')
WHERE p.price_id IS NULL
推荐阅读
- sql - 使用来自选择查询的数据更新表,包括第二个表
- javascript - 在 AppModule 中导入不必要的模块会减慢 Angular 2 应用程序的速度吗?
- sql - ORA-00907: 查询 ALTER TABLE Table_Name MODIFY Column_Name 缺少右括号
- php - 如何在php中删除`@`之前的发件人姓名
- amazon-web-services - AWS VPC - k8s - 负载均衡
- docker-compose - Traefik 重定向前端服务不起作用
- java - 如何在spring-boot数据休息的POST json中传递@EmbeddedId
- google-apps-script - Apps 脚本错误 - 找不到方法 getRange(number,number,(class),number)
- c# - 从单个路径删除级联删除
- javascript - 当它们准备好时,使用 angular 中的 observable 值