2010-01-15 86 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