SQL Server:如何使用Cursor删除记录

时间:2010-01-20 03:13:59

标签: sql sql-server sql-server-2000

我们希望删除表中的大量过时数据,但这会长时间锁定表。是否可以使用Cursor删除,说,在while循环中每个事务一百条记录?

我在哪里可以参考这个例子?

3 个答案:

答案 0 :(得分:2)

这样的事情:

DECLARE @stillgoing bit;
SET @stillgoing = 1;

WHILE @stillgoing = 1
BEGIN
  DELETE TOP (100) YourTableName
  WHERE IsObsolete = 1;

  IF @@ROWCOUNT = 0
      SET @stillgoing = 0;

  CHECKPOINT /* Will encourage the log to clear if it's in Simple recovery model */
END

编辑:这只适用于SQL 2005及以上版本。正如我们刚刚学会的那样是SQL 2000,而不是这个代码:

DECLARE @stillgoing bit
SET @stillgoing = 1

SET ROWCOUNT 100

WHILE @stillgoing = 1
BEGIN
  DELETE YourTableName
  WHERE IsObsolete = 1

  IF @@ROWCOUNT = 0
      SET @stillgoing = 0

  CHECKPOINT /* Will encourage the log to clear if it's in Simple recovery model */
END

并且...简单恢复模型意味着日志将在检查点上截断,而不是仅在备份日志时截断。

答案 1 :(得分:1)

你可以在循环中提交每100(或1000或其他)记录,释放锁并让任何待处理的操作得到它们的工作。否则你生成一个大于O的巨大事务日志(n ^ 2)变大的时间。这个东西将占用实际花费的很大一部分,而不是实际删除。如果批量和提交,你会更安全,回滚/日志文件不会像疯了一样增长,并且锁是可管理的。

如果您需要大量回滚作为选项,则有两种选择:

  • 等了很久
  • 先备份表格,然后进行批量删除

答案 2 :(得分:1)

Declare MyPrimaryKey [SomeType]

Declare @MyCursor Cursor For 

Select MyPrimayKey from MyTable

Open @MyCursor

Fetch Next From @MyCursor

Into
  @MyPrimaryKey

WHILE @@FETCH_STATUS = 0

BEGIN
   WaitFor Delay '00:00:05'

   Begin Transaction

   DELETE From MyTable where MyPrimaryKey = @MyPrimaryKey

   Commit Transaction

   Fetch Next From @MyCursor

   Into
     @MyPrimaryKey
END