2010-01-15 59 views
5

我有一個在sql server 2008上運行的存儲過程,循環遍歷大約5000萬行的表,每天有一天刪除記錄(每天大約25,000條記錄)。我希望能夠在流程通過打印語句運行到消息窗口時觀察到這種情況。我希望每次發生一天的刪除操作時都能看到一條消息。有沒有辦法做這樣的事情?該過程大致佈局是這樣的:Sql Server在while循環期間打印受影響的行

WHILE EXISTS(<query statement>) 
BEGIN 

BEGIN TRAN 

DELETE 
FROM <table> 
WHERE <condition> 
AND <condition> 

--need some sort of "rows affected" statement here 

COMMIT 

END 

回答

20

不幸的是,PRINT語句輸出被纏繞起來,而不是立即寫入到輸出。一個辦法解決這是使用RAISERROR這樣的:

RAISERROR ('MY MESSAGE', 0, 1) WITH NOWAIT 

特別是你想要的東西:

DECLARE @Msg VARCHAR(200) 

    WHILE EXISTS(<query statement>) 
    BEGIN 
    BEGIN TRAN 

    DELETE 
    FROM <table> 
    WHERE <condition> 
    AND <condition> 

    SELECT @Msg = CAST(@@ROWCOUNT AS VARCHAR(10)) + ' rows affected' 
    RAISERROR (@Msg, 0, 1) WITH NOWAIT 

    COMMIT 
    END 

我也傾向於在消息中包含當前時間,所以我可以記錄與時間進度。

+0

這工作,但我還是不太清楚如何抓住受每批期間刪除的行數。對此有何想法? – Kevin 2010-01-15 15:20:57

+1

@Kevin - 查看我的更新:) – AdaTheDev 2010-01-15 15:22:17

+0

謝謝!這工作:) – Kevin 2010-01-15 15:29:31

2

比select @@ rowcount更復雜嗎?

+0

不錯,非常複雜! – alfadog67 2017-04-21 18:02:27

0

如何使用OUTPUT子句?你可以從存儲過程寫入SQL Server控制檯嗎?

就像在觸發器中一樣,您的手中有一個「已刪除」僞表,其中包含正在刪除的行及其所有列。

WHILE EXISTS(<query statement>) 
BEGIN 
    BEGIN TRAN 

    DELETE FROM <table> 
    OUTPUT deleted.ID, deleted.TimeStamp -- or whatever 
    WHERE <condition> 
    AND <condition> 

    COMMIT 

END 
+0

我不一定希望看到每批被刪除的每行,但只是它們的總數。我不確定你可以通過OUTPUT子句獲得該功能。 – Kevin 2010-01-15 15:20:20

+0

您可以將OUTPUT指向臨時表,然後在WHILE循環之後對該臨時表中的行進行計數。 – 2010-01-15 15:45:09

0

我以前做類似這樣的東西,因爲在那裏纏繞了打印是沒有多大用處,但我發現,在命令行實用程序osql輸出他們立即,所以我寫的存儲過程,並把它稱爲從一個批處理文件,而讓我看到進展。

0

執行以下操作:

DECLARE @queryCount AS INT, @start AS INT, @stop as INT, @table as varchar(max) 

SELECT @start = cnt(*) as a FROM <table> 

SELECT @queryCount = cnt(*) 
    FROM <table> 
    WHERE <condition> 
    AND <condition> 

DELETE 
    FROM <table> 
    WHERE <condition> 
    AND <condition> 

SELECT @stop = cnt(*) as a FROM <table> 

PRINT(convert(varchar(max), @queryCount) + ' rows deleted from ' + convert(varchar(max), @table)) 

如果你想驗證,您可以在下面的代碼拋出。

PRINT('Rows at start: ' + convert(varchar(max), @start)) 
PRINT('Rows at end: ' + convert(varchar(max), @stop)) 
PRINT('Row difference: ' + convert(varchar(max), @start - @stop)) 

警告:如果在發生這種情況時數據庫可能會影響行,則可能會看到差異。

0

你可以做這樣的事情來遍歷每個行

  declare @ii (id int) table 

    -- for batchchunk operations  

      declare @numTransactions as int = 0,   
      @totalRowsInserted as int = 0,   
      @chunksize int = 0,   
      @printnow varchar(1000)  


     --does the initial insert into the table  
      select * from #table  
      SET @numTransactions [email protected]@rowcount  
      SET @printnow = 'Should Insert :'+cast(@numTransactions as varchar)+ ' rows into the table.'   
      exec db.printNow @printnow;  -- shortened proc 

      BEGIN   
      INSERTCHUNKS:   

      SET ROWCOUNT @Batchsize     



      insert into table     
      (     
      type_id,     
      parent_id,     
      created_by_user_id,     
      created_at,     
      updated_by_user_id,     
      updated_at,     
      created_by_system_id,     
      updated_by_system_id,     
      is_deleted     
      )     
      output inserted.id into @ii(id)     

      select     
      1,--party_type_id     
     NULL,--parent_party_id     
     @user_id, --created_by_user_id     
     case when created_at is NULL then getdate() else created_at end ,        

     NULL , --updated_by_user_id     
     case when updated_at is NULL then getdate() else updated_at end, -- 
     updated_at     
     case when created_by_system_id is null then 292 else 0 end, --created_by_system_id     
      updated_by_system_id,--updated_by_system_id     \ 
      0 --is_deleted     
     from     
     #table   
     order by id asc    
     OFFSET    
     @TotalRowsInserted ROWS   
     FETCH NEXT @batchsize ROWS ONLY  
     set @chunksize [email protected]@rowcount    
      IF @chunksize > 0  
      BEGIN    
     set @totalRowsInserted = @totalRowsInserted + @chunksize    
      SET @printnow = 'Batch done: ' + 
      cast(@chunksize as varchar) + ' rows in Batch ; '   
      + cast(@totalRowsInserted as varchar) + ' total inserted so far 
      into the table.'    exec db.printnow @printnow;    

      waitfor delay '00:00:01'   
      GOTO INSERTCHUNKS   
      END   
      SET ROWCOUNT 0;  
      END