递归“ON DUPLICATE KEY UPDATE”

时间:2010-11-26 22:11:06

标签: sql datetime mysql recursion unique-constraint

我在日期列上有一个带有UNIQUE键的数据库表,因此每个日期永远不会有多行。如果我为数据库中已存在的一天插入一个新行,我希望它将所有后续的连续日期推回一天,直到它达到“免费”日。

这就是我的想法:

INSERT INTO
 `activity`
 (`name`,`date`)
VALUES
 ('date 7','2009-07-31')
ON DUPLICATE KEY
 UPDATE `date` = DATE_ADD(`date`, INTERVAL '1' DAY)

我的想法是,ON DUPLICATE KEY UPDATE会在桌面上冒泡并继续每天添加一天,直到它到达不存在的那一天。

例如,如果我的表格内容如下:

date 1, 2009-07-30
date 2, 2009-07-31
date 3, 2009-08-01
date 4, 2009-08-02
date 5, 2009-08-04 <- notice this date is two days past the previous one

...我将在2009-07-31插入'date 7',我希望这样做:

date 1, 2009-07-30
date 7, 2009-07-31 <- newly inserted row
date 2, 2009-08-01 <- this and subsequent rows are all incremented
                      by one day until it hits a non-consecutive day
date 3, 2009-08-02
date 4, 2009-08-03
date 5, 2009-08-04 <- notice this date hasn't changed

但是在重复密钥更新不能像这样工作时,它只更新冲突行,如果该行然后与另一行冲突,则它会因重复键错误而退出。

有没有一种聪明的方法可以单独在SQL中实现这种效果?

2 个答案:

答案 0 :(得分:2)

查询目标日期或之后的第一个免费日期。这涉及左自联接以查找表中没有后继的日期。

SELECT DATE_ADD(Min(a.`date`), INTERVAL '1' DAY) AS `free_date`
FROM `activity` a
LEFT JOIN `activity` z
ON z.`date` = DATE_ADD(a.`date`, INTERVAL '1' DAY)
WHERE z.`date` IS NULL 
AND a.`date` >= '2009-07-31'

运行更新以增加目标日期与第一个空闲日期之间范围内的每个日期。

现在有空间可以插入所需的插页。

答案 1 :(得分:0)

在执行更新之前选择最长日期,然后将一天添加到最大值

类似的东西:

ON DUPLICATE KEY

 UPDATE `date` = DATE_ADD(select max('date') from 'activity', INTERVAL '1' DAY)