Sql Server在while循环期间打印受影响的行

时间:2010-01-15 14:57:43

标签: sql-server sql-server-2008 stored-procedures printing

我有一个在sql server 2008上运行的存储过程,循环遍历大约5000万行的表,一次删除一天的记录(每天大约25,000条记录)。我希望能够在流程通过print语句运行到消息窗口时观察到这种情况。我希望每次每天都有一次删除操作时能够看到一条消息。有没有办法做这样的事情?程序大致如下:

WHILE EXISTS(<query statement>)
BEGIN

BEGIN TRAN

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

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

COMMIT

END

6 个答案:

答案 0 :(得分:23)

不幸的是,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

我也倾向于在消息中包含当前时间,以便我可以记录进度与时间的关系。

答案 1 :(得分:2)

比选择@@ rowcount更复杂吗?

答案 2 :(得分: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

答案 3 :(得分:0)

我曾经做过与此类似的事情,因为假冒的打印件并没有多大用处,但我发现命令行实用程序osql会立即输出它们,所以我编写了存储过程并调用它而是从批处理文件中,让我看到进度。

答案 4 :(得分: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))

警告:如果数据库在进行此操作时可能会影响行,则可能会出现差异。

答案 5 :(得分: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 =@@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 =@@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