2016-05-17 105 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) 

對不起,我沒有測試第二個代碼之前跟蹤記錄。請原諒我,如果它打破了一些東西。但我很確定它可能需要一個小修復才能使這個查詢功能。祝一切順利。

相關問題