我试图在SQL SERVER中使用while循环而不是CURSOR。我正在尝试选择TOP 1,并将它们设置为如下变量。它不允许我在while循环中设置变量。我做错了什么?
WHILE (
SELECT TOP 1 @WAOR_CODE = WAOR_.WAOR_CODE
, @WAOD_INVENTORYITEMID = WAOD_.WAOD_INVENTORYITEMID
FROM #wmsorder
)
BEGIN
SELECT @WAOR_CODE
, @WAOD_INVENTORYITEMID
DELETE TOP (1) #wmsorder
END
答案 0 :(得分:4)
另一种选择:
WHILE EXISTS(select 1 FROM #wmsorder)
BEGIN
DELETE TOP (1)
FROM #wmsorder
END
然而,逐个删除表中的所有记录可能是一个性能地狱。您可能需要考虑使用TRUNCATE TABLE
代替:
TRUNCATE TABLE #wmsorder
另请注意,每次删除都会写入数据库日志,而truncate table根本不会写入日志。
使用包含100,000行的临时表进行测试,逐个删除行需要9秒,而截断表立即完成:
-- create and populate sample table
SELECT TOP 100000 IDENTITY(int,1,1) AS Number
INTO #wmsorder
FROM sys.objects s1
CROSS JOIN sys.objects s2
-- delete rows one by one
WHILE EXISTS(select 1 FROM #wmsorder)
BEGIN
DELETE TOP (1)
FROM #wmsorder
END
-- clean up
DROP TABLE #wmsorder
-- create and populate sample table
SELECT TOP 100000 IDENTITY(int,1,1) AS Number
INTO #wmsorder
FROM sys.objects s1
CROSS JOIN sys.objects s2
-- truncate the table
TRUNCATE TABLE #wmsorder
-- clean up
DROP TABLE #wmsorder
答案 1 :(得分:3)
DECLARE @t TABLE (a INT PRIMARY KEY)
INSERT INTO @t
VALUES (1), (2), (3)
变体#1:
label:
DELETE TOP(1)
FROM @t
OUTPUT DELETED.a
IF @@ROWCOUNT > 0
GOTO label
变体#2:
WHILE @@ROWCOUNT != 0
DELETE TOP(1)
FROM @t
OUTPUT DELETED.a
变体#3:
DECLARE @a TABLE(a INT)
WHILE @@ROWCOUNT != 0 BEGIN
DELETE FROM @a
DELETE TOP(1)
FROM @t
OUTPUT DELETED.a INTO @a
SELECT * FROM @a
END
答案 2 :(得分:0)
请参阅以下代码。我刚刚更正了你分享的SQL语句
WHILE 1=1
BEGIN
IF NOT EXISTS (SELECT 1 FROM #wmsorder)
BREAK
SELECT TOP 1 @WAOR_CODE = WAOR_.WAOR_CODE
,@WAOD_INVENTORYITEMID = WAOD_.WAOD_INVENTORYITEMID
FROM #wmsorder WAOR_
SELECT @WAOR_CODE
,@WAOD_INVENTORYITEMID
DELETE #wmsorder WHERE WAOR_CODE = @WAOR_CODE AND WAOD_INVENTORYITEMID = @WAOD_INVENTORYITEMID
END
但正如Zohar Peled所说,如果你从一张桌子上逐一删除记录,那么引擎会很痛苦。所以下面我分享了另一个查询,通过这个甚至你可以在删除表之前跟踪记录
DECLARE @TableVar AS TABLE (WAOR_CODE VARCHAR(100), WAOD_INVENTORYITEMID VARCHAR(100))
WHILE 1=1
BEGIN
SELECT TOP 1 @WAOR_CODE = WAOR_.WAOR_CODE
,@WAOD_INVENTORYITEMID = WAOD_.WAOD_INVENTORYITEMID
FROM #wmsorder WAOR_
WHERE NOT EXISTS (SELECT 1 FROM @TableVar t WHERE t.WAOR_CODE = WAOR_.WAOR_CODE AND t.WAOD_INVENTORYITEMID = WAOR_.WAOD_INVENTORYITEMID)
IF @WAOR_CODE IS NULL AND @WAOD_INVENTORYITEMID IS NULL
BREAK
INSERT INTO @TableVar
(WAOR_CODE, WAOD_INVENTORYITEMID)
SELECT @WAOR_CODE
,@WAOD_INVENTORYITEMID
END
DELETE #wmsorder WHERE EXISTS (SELECT 1 FROM @TableVar t WHERE t.WAOR_CODE = #wmsorder.WAOR_CODE AND t.WAOD_INVENTORYITEMID = #wmsorder.WAOD_INVENTORYITEMID)
抱歉,我没有测试第二个代码。如果它破坏了什么,请原谅我。但我很确定它可能需要一个小修复才能使这个查询起作用。一切顺利。