2016-05-17 73 views
3

我想在while循环而不是在SQL SERVER中使用CURSOR。我正在尝试在while中选择TOP 1并将它们设置为如下所示的变量。它不让我在while循环中设置变量。我究竟做错了什么?如何在While循环中设置变量在SQL Server中

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 

回答

4

另一种选择:

WHILE EXISTS(select 1 FROM #wmsorder) 
BEGIN 
    DELETE TOP (1) 
    FROM #wmsorder 
END 

但是,从表中逐一删除所有记录可能是一个表现地狱。您可能要考虑使用TRUNCATE TABLE代替:

TRUNCATE TABLE #wmsorder 

另外请注意,每个删除写入到数据库的日志,同时截断表不会被写入日志的。

测试包含100,000行,删除行一个接一个的临时表花了我9秒,而将truncate table立即完成:

-- 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 
+0

我一个接一个地删除行因为我试图摆脱我使用的行。 –

+0

我明白了。在这种情况下,您可能需要重新考虑整个脚本。你可能会发现一个基于集合的方式,无论你如何处理这些数据,而是逐一消耗行。 –

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 
+0

这是最快的吗?我从来没有想过这种方法 –

+1

@ayilmaz,迭代处理总是缓慢 – Devart

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 

但作为琐佩莱德提到的那样,这将是一个痛苦的引擎,如果你删除的记录,一个接一个从表。所以,下面我有共同的另一个查询,通过这个甚至可以从表中删除

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) 

对不起,我没有测试第二个代码之前跟踪记录。请原谅我,如果它打破了一些东西。但我很确定它可能需要一个小修复才能使这个查询功能。祝一切顺利。

相关问题