代码之家  ›  专栏  ›  技术社区  ›  BCS

在SQL表之间移动行

  •  5
  • BCS  · 技术社区  · 16 年前

    我有两张表,一张活动表和一张不活动表。我想 移动 从活动表到非活动表的行。我的第一个想法是

    insert into inactive select * from active where ...
    delete from active active where ...
    

    然而大约在.42秒后,我注意到如果更新改变了WHERE子句选择的内容,这将删除/复制行。

    在这种情况下,我可以很容易地预防这种情况,但是如果我不能,我应该怎么做呢?

    编辑:从答案来看,似乎没有一种简单/琐碎的方法可以做到这一点。我真的很惊讶。我认为拥有它会有一些实质性的好处。

    8 回复  |  直到 16 年前
        1
  •  8
  •   S.Lott    16 年前

    状态标志是您的朋友。

    UPDATE old_data SET move="MARKED";
    INSERT INTO somewhere... SELECT where move="MARKED";
    DELETE FROM old_data WHERE move="MARKED";
    

    如果在自动提交关闭的情况下执行此操作,它将在整个位置锁定锁。

    如果您想减少一点锁定,可以在每一步之后提交。

        2
  •  4
  •   Arvo    16 年前

    (至少在MS SQL中)您可以使用事务和锁定提示:

    begin tran
    
    insert into inactive
    select * from active with (updlock)
    where ...
    
    delete from active
    where ...
    
    commit tran
    

    如果有人更改了正在删除的记录,则可能会发生不带锁提示(updlock)的死锁。

        3
  •  4
  •   Örjan Jämte    16 年前

    您的数据库支持OUTPUT子句吗?那么这对你来说可能是一个完美且易于理解的解决方案,不是吗?

    http://msdn.microsoft.com/en-us/library/ms177564.aspx

    delete active with (readpast)
    output DELETED.*
    into inactive
    where ...
    
        4
  •  1
  •   Bill Karwin    16 年前

    如果您可以悲观地锁定行,也就是说,当您读取这些行以将它们复制到不活动的表中时,就没有人可以从您的下面更改它们。

    锁定行的方法因数据库品牌而异,您在问题中没有指定。

        5
  •  1
  •   Nick DeVore    16 年前

    声明一个本地表变量并将这些值放入其中,将它们插入到非活动表中,然后从本地列表中的活动表中删除行。

    不过,交易理念也同样有效。

        6
  •  1
  •   John MacIntyre    16 年前

    使用唯一的ID列

    delete from active where rowid in (select rowid in inactive)
    

    delete from active as a 
    where exists (select * 
                  from inactive 
                  where pkfld1=a.pkfld1 
                  and pkfld2=a.pkfld2)
    

    另外,不要忘记在事务中包装这个过程。

    祝你好运。

        7
  •  0
  •   Amy B    16 年前

    这就是我保存where子句的方式:

    DECLARE @MyTable TABLE
    (
      TheKey int PRIMARY KEY
    )
    --
    INSERT INTO @MyTable(TheKey)
    SELECT TheKey FROM SourceTable WHERE rows I want
    --
    INSERT INTO Inactive(fieldlist)
    SELECT fieldlist
    FROM Active
    WHERE TheKey IN (SELECT TheKey FROM @MyTable)
    --
    DELETE
    FROM Active
    WHERE TheKey IN (SELECT TheKey FROM @MyTable)
    

    如果您需要比这更强大的功能,那么您需要查看锁定(在事务期间阻止更改)。

        8
  •  0
  •   dkretz    16 年前

    为什么你有两张桌子,而不是一栏“isactive”?