在SQL中的表之间移动行

时间:2008-11-18 20:59:27

标签: sql partitioning

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

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

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

在这种情况下,我可以很容易地防止这种情况,但在我无法做到的情况下该怎么办?

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

8 个答案:

答案 0 :(得分:8)

状态标志是你的朋友。

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

如果在关闭Autocommit的情况下执行此操作,它将占用整个地方的锁定。

如果你想减少锁定,你可以在每一步之后进行COMMIT。

答案 1 :(得分:4)

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

begin tran

insert into inactive
select * from active with (updlock)
where ...

delete from active
where ...

commit tran

如果没有锁定提示(updlock),可能会发生死锁,如果有人确实更改了被删除的记录。

答案 2 :(得分:4)

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

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

delete active with (readpast)
output DELETED.*
into inactive
where ...

答案 3 :(得分:1)

如果您可以悲观地锁定行,那就是当您阅读它们以将它们复制到非活动表中时,那么没有人可以将它们从您下面更改出来。

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

答案 4 :(得分:1)

声明一个本地表var并将值放入那里,将它们插入到非活动表中,然后从活动表中删除本地列表中的行。

交易理念也同样适用。

答案 5 :(得分:1)

使用像

这样的唯一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)

另外,不要忘记在事务中包装此进程。

祝你好运。

答案 6 :(得分:0)

这就是我保留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)

如果您需要比这更强大,您需要查看锁定(在交易期间阻止更改)。

答案 7 :(得分:0)

为什么你有两个表,而不是“IsActive”的列?