在循环中删除表行

时间:2013-12-04 13:55:31

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

我们正在使用SQL Server 2000.我们拥有一个包含超过100000张图像的繁重数据库。目前我正在使用此查询删除记录:

DELETE FROM T_JBSHEETDATA
WHERE (F_JBREF NOT IN (SELECT JOB_REF_NUMBER
                       FROM  T_JBDTLS))

但不幸的是,它一次只能删除500条记录。如果我采取更多记录服务器死亡(服务器超时)。如何创建x行循环直到它完成?

3 个答案:

答案 0 :(得分:1)

以下是“前N删除”的方法。

一些想法。您可以配置@TopSize,直到找到良好的“goldie locks”值。不是太大,也不是太小。

你也可以删除while循环,然后跟踪@RowCount(在删除语句之后)......如果你有客户端代码....返回delete-count,并继续调用(存储过程?)反复删除计数为零。

现在,我会看到一个索引是否可以在诉诸下面之前提高性能。 但我正在试着回答你的问题..............如所问的那样。

/* START TSQL */

if exists (SELECT * FROM information_schema.tables WHERE table_schema = 'dbo' and table_name = 'Television')
      BEGIN
            DROP TABLE [dbo].[Television]
      END
GO


CREATE TABLE [dbo].[Television] (
      TelevisionUUID [uniqueidentifier] not null default NEWSEQUENTIALID() ,
      TelevisionName varchar(64) not null ,
      TelevisionKey int not null ,
      IsCheckedOut bit default 0
)    
GO


ALTER TABLE dbo.Television ADD CONSTRAINT PK_Television_TelevisionUUID
PRIMARY KEY CLUSTERED (TelevisionUUID)
GO


ALTER TABLE dbo.Television ADD CONSTRAINT CK_Television_TelevisionName_UNIQUE
UNIQUE (TelevisionName)
GO


set nocount on

declare @counter int
select @counter = 11000
declare @currentTVName varchar(24)
declare @TopSize int
select @TopSize = 10

while @counter > 10000  /* this loop counter is ONLY here for fake data,….do not use this syntax for production code */
begin

      select @currentTVName = 'TV:     '+ convert(varchar(24) , @counter)

      INSERT into dbo.Television ( TelevisionName , TelevisionKey ) values ( @currentTVName , @counter)

      select @counter = @counter - 1     
end


/* Everything above is just setup data, the crux of the code is below this line */


select count(*) as TV_Total_COUNT_Pre from dbo.Television

declare @DeleteLoopCounter int 
select @DeleteLoopCounter = 0

while exists ( select top 1 * from dbo.Television )

 BEGIN
        select @DeleteLoopCounter = @DeleteLoopCounter + 1

        ;
        WITH cte1 AS      
         (  SELECT
              TOP (@TopSize)

           TelevisionUUID ,  /* <<Note, the columns here must be available to the output */
           IsCheckedOut       
              FROM  
                    dbo.Television tv     
            WITH ( UPDLOCK, READPAST , ROWLOCK )  /* <<Optional Hints, but helps with concurrency issues  */

              /* WHERE conditions can be put there as well */

              ORDER BY /* order by is optional, and I would probably remove it for a delete operation */
                    tv.TelevisionKey DESC       
        )
                                      /* UPDATE cte1 SET  IsCheckedOut = 1 */ /* this code has nothing to do with the delete solution, but shows how you could use this same trick for an "update top N" */

        Delete deleteAlias
        from dbo.Television deleteAlias
        where exists ( select null from cte1 innerAlias where innerAlias.TelevisionUUID = deleteAlias.TelevisionUUID )
        ;

        print '/@DeleteLoopCounter/'
        print @DeleteLoopCounter
        print ''

        select count(*) as TV_Total_COUNT_Post from dbo.Television

    END

修改

Sql Server 2000特定信息:

请注意。由于你有2000,你将需要HARD代码@TopSize值。但我将为未来的读者留下“原样”的代码。同样,您必须删除@TopSize,然后使用类似“1000”或类似的值。删除选择附近的@TopSize周围的()。

答案 1 :(得分:0)

您可以提高查询的性能,而不是试图弄清楚如何在循环中删除。

1。确保表T_JBDTLS.JOB_REF_NUMBER上有索引。如果它丢失可能是导致经济放缓的原因。

2. 更改您的查询以使用联接而不是子选择。类似的东西:

  DELETE FROM T_JBSHEETDATA
    FROM T_JBSHEETDATA D
        LEFT JOIN T_JBDTLS J ON D.F_JBREF = J.JOB_REF_NUMBER
    WHERE J.JOB_REF_NUMBER IS NULL

3。您要删除的桌面上是否有任何触发器? cascade删除怎么样?正在级联删除的表上的触发器?

答案 2 :(得分:0)

您可能还想尝试“不存在”子句而不是“不在”。

我相信以下是正确的翻译。

Delete deleteAlias
/* select deleteAlias.* */
from dbo.T_JBSHEETDATA deleteAlias
where not exists ( select null from dbo.[T_JBDTLS] innerDets where innerDets.JOB_REF_NUMBER = deleteAlias.F_JBREF )

这是一个通用的Northwind版本,它将删除任何没有任何(子)订单详细信息的订单。

Use Northwind
GO


Delete deleteAlias
/* select deleteAlias.* */
from dbo.Orders deleteAlias
where not exists ( select null from dbo.[Order Details] innerDets where innerDets.OrderId = deleteAlias.OrderId )