【问题标题】:Recursive "ON DUPLICATE KEY UPDATE"递归“ON DUPLICATE KEY UPDATE”
【发布时间】:2011-05-16 09:20:30
【问题描述】:

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

这是我的想法:

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 插入“日期 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 中实现这个效果?

【问题讨论】:

    标签: sql datetime mysql recursion unique-constraint


    【解决方案1】:

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

    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'
    

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

    现在有空间放置您想要的插入。

    【讨论】:

    • 我认为您应该将 LEFT 更改为 INNER JOIN。
    • @Lieven:它必须是左连接,因为我们要检索的记录是缺少后续日期的记录。
    • 抱歉,时间不早了。我一直在打字,但我的大脑已经关闭了。
    【解决方案2】:

    在更新前选择最大日期,然后在最大日期上加一天

    类似的东西:

    在重复键上

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-09-04
      • 2014-03-10
      • 2013-10-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-01
      相关资源
      最近更新 更多