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)");
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 完全没有学习过GAN,看了CSDN的一篇文章,里面有代码但是完全不知道如何操作
  • ¥15 使用ue5插件narrative时如何切换关卡也保存叙事任务记录
  • ¥20 软件测试决策法疑问求解答
  • ¥15 win11 23H2删除推荐的项目,支持注册表等
  • ¥15 matlab 用yalmip搭建模型,cplex求解,线性化处理的方法
  • ¥15 qt6.6.3 基于百度云的语音识别 不会改
  • ¥15 关于#目标检测#的问题:大概就是类似后台自动检测某下架商品的库存,在他监测到该商品上架并且可以购买的瞬间点击立即购买下单
  • ¥15 神经网络怎么把隐含层变量融合到损失函数中?
  • ¥15 lingo18勾选global solver求解使用的算法
  • ¥15 全部备份安卓app数据包括密码,可以复制到另一手机上运行