doutizha7526 2014-12-01 10:13
浏览 69
已采纳

在mysql中使用时间戳条件将数据插入一个表中,从另一个表中删除

In short

Is there a safe way to move database entries - based on a timestamp condition - to another table (without first querying the time)? So that it is ensured, INSERT INTO works on the exact same entries as DELETE?

Background to the question

  • This question is not about the importance of using transactions, that is a given! But rather it is about the problem that the time (eg. the value of NOW()) might be different for the two subsequent queries.
  • Since a programming framework is used, which does (for safety reasons) not allow multiple queries being executed in a single call, this really becomes an issue

Example table structure

Source
---------------------------------------------
ID        |  Timeout              |  Data
---------------------------------------------
1         |  2014-12-31 12:00:00  |  foo
2         |  2014-12-31 15:00:00  |  bar
3         |  2014-12-31 18:00:00  |  foobar

Archive
---------------------------------------------
ID        |  Data
---------------------------------------------

Demonstration (simplified)

<?php

    beginTransaction();
    try {
        // Imagine this happens at 2014-12-31 14:59:59(.992) [Entry #2 not copied]
        execute( "INSERT INTO Archive (ID, Data) 
                      SELECT ID, Data FROM Source
                      WHERE Timeout <= NOW()" );

        // While here it might be already 2014-12-31 15:00:00(.004) [Entry #2 deleted]
        execute("DELTE FROM Source WHERE Timeout <= NOW()");
        commit();
    }
    catch (Exception $e) {
        rollBack();
        return false;
    }

    return;
?>

So is there a safe way to evade this problem, preferably with performance in mind (I know, in this case php might be the wrong language in the first place ^^). Help much appreciated!

  • 写回答

1条回答 默认 最新

  • douchongbc72264 2014-12-01 10:43
    关注
    execute("SET @now = NOW()");
    
    execute("
        INSERT INTO Archive (ID, Data) 
        SELECT ID, Data 
        FROM Source
        WHERE Timeout <= @now
    ");
    
    execute("DELTE FROM Source WHERE Timeout <= @now");
    

    OR

    execute("
        INSERT INTO Archive (ID, Data) 
        SELECT ID, Data 
        FROM Source
        WHERE Timeout <= NOW()
    ");
    
    execute("DELTE FROM Source WHERE Timeout <= (SELECT MAX(Timeout) FROM Archive)");
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 delta降尺度计算的一些细节,有偿
  • ¥15 Arduino红外遥控代码有问题
  • ¥15 数值计算离散正交多项式
  • ¥30 数值计算均差系数编程
  • ¥15 redis-full-check比较 两个集群的数据出错
  • ¥15 Matlab编程问题
  • ¥15 训练的多模态特征融合模型准确度很低怎么办
  • ¥15 kylin启动报错log4j类冲突
  • ¥15 超声波模块测距控制点灯,灯的闪烁很不稳定,经过调试发现测的距离偏大
  • ¥15 import arcpy出现importing _arcgisscripting 找不到相关程序