我们正在使用SQL Server 2000.我们拥有一个包含超过100000张图像的繁重数据库。目前我正在使用此查询删除记录:
DELETE FROM T_JBSHEETDATA
WHERE (F_JBREF NOT IN (SELECT JOB_REF_NUMBER
FROM T_JBDTLS))
但不幸的是,它一次只能删除500条记录。如果我采取更多记录服务器死亡(服务器超时)。如何创建x行循环直到它完成?
答案 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 )