2016-03-07 41 views
0

我們正試圖運行一個WHILE循環中的一個DELETE聲明(避免大事務日誌大量的行)如下:@@ ROWCOUNT的初始值跨數據庫和服務器的變化

WHILE (@@ROWCOUNT > 0) 
    BEGIN 
     DELETE TOP (250000) 
     FROM 
      MYDATABASE.MYSCHEMA.MYTABLE 
     WHERE 
      MYDATABASE.MYSCHEMA.MYTABLE.DATE_KEY = 20160301 
    END 

當這命令在我們的開發環境中的新SQL Server Management Studio連接中執行,它會刪除250K塊中的行,這是預期的行爲。

當這個命令被以同樣的方式我們測試服務器上執行,我們得到

Command completed successfully 

也就是說,已運行的語句時沒有輸入WHILE循環的消息。

經過一些額外的調查後,我們發現行爲也取決於我們連接到的數據庫。因此,如果代碼運行時(在我們的測試環境中),而SQL Server Management Studio連接到MYDATABASE時,DELETE語句不運行。如果我們在連接到SOME_OTHER_DATABASE的情況下運行代碼,它會執行。

我們部分懷疑@@ROWCOUNT的值不可靠,並且可能因不同的連接而不同。但是,當我們爲每個數據庫服務器組合多次運行代碼時,我們會看到100%一致的行爲。因此,@@ROWCOUNT的隨機初始值不會解釋事情。

有關可能會發生什麼的任何建議?謝謝你的幫助!

編輯#1

對於詢問的@@ROWCOUNT的初始值,它是從哪裏來的,我們不知道。但是在某些情況下,@@ROWCOUNT肯定被初始化爲零以上的某個值,因爲代碼按原樣在新連接上工作。

編輯#2

對於那些提出我們自己的變量聲明,因爲我們是通過編程語言包裝只允許一個語句的執行在同一時間執行SQL命令我們的特定應用(即一個分號)。

我們曾試圖通過循環之前執行一個delete語句建立的@@ROWCOUNT值:

聲明#1:

DELETE TOP (250000) 
FROM 
    MYDATABASE.MYSCHEMA.MYTABLE 
WHERE 
    MYDATABASE.MYSCHEMA.MYTABLE.DATE_KEY = 20160301 

聲明#2(@@ROWCOUNT大概是現在250,000):

WHILE (@@ROWCOUNT > 0) 
    BEGIN 
     DELETE TOP (250000) 
     FROM 
      MYDATABASE.MYSCHEMA.MYTABLE 
     WHERE 
      MYDATABASE.MYSCHEMA.MYTABLE.DATE_KEY = 20160301 
    END 

然而,無論是造成@@ROWCOUNT採取在啓動不同的值也是在命令之間創建值。所以在某些情況下,第二條語句從不執行。

回答

2

在設置其值之前,不應使用變量。對於系統變量也是如此。

您擁有的代碼非常危險。有人可以在delete之後添加諸如SELECT 'Here I am in the loop'之類的內容,並且它會中斷。

更好的方法?使用你自己的變量:

DELCARE @RC int; 
WHILE (@RC > 0 OR @RC IS NULL) 
    BEGIN 
     DELETE TOP (250000) 
     FROM MYDATABASE.MYSCHEMA.MYTABLE 
     WHERE MYDATABASE.MYSCHEMA.MYTABLE.DATE_KEY = 20160301; 

     SET @RC = @@ROWCOUNT; 
    END; 
0

你在哪裏得到你的初始@@ROWCOUNT從?我的意思是,你永遠不會進入該塊,因爲@@ROWCOUNT預計爲零,所以你永遠不會進入循環。此外,在250K批次中刪除不會改變事務日誌的大小 - 如果您正在記錄日誌,所有刪除操作都將被記錄下來,因此在循環中執行此操作沒有任何好處(也有一些處罰)。

+0

我的印象是事務日誌在每個'BEGIN' ...'END'塊之後被清除。對於涉及數千萬條記錄的較低開銷刪除語句,您會採用什麼方法? – wk2752

+0

不是。事務日誌保留,以便您可以構建完整的備份。做一個完整的備份告訴SQL Server你有一個新的起點,所以它可以清空那個事務日誌。如果你不想*交易,你可以'截斷日誌',但是......我想這不是一個好主意。 –

0

你是否追蹤了會話?由於@@ROWCOUNT返回會話中先前語句影響的行數,我猜想最後一個查詢SSMS作爲建立會話的一部分執行會返回兩個環境中不同數量的行,或者您有一個登錄觸發器其最後一條語句返回不同行數的一個或另一個環境。無論哪種方式,痕跡都應該告訴你爲什麼行爲是不同的。

從根本上說,雖然,這是沒有意義的參考@@ROWCOUNT你運行你有興趣獲得一算語句之前。使用變量很容易解決這個問題

DECLARE cnt integer = -1; 
WHILE (cnt != 0) 
BEGIN 
    DELETE TOP (250000) 
    FROM MYDATABASE.MYSCHEMA.MYTABLE 
    WHERE MYDATABASE.MYSCHEMA.MYTABLE.DATE_KEY = 20160301; 
    SET cnt = @@ROWCOUNT; 
END