2010-01-15 16 views
5

Tengo un procedimiento almacenado ejecutándose en el servidor sql 2008 que recorre una tabla de ~ 50 millones de filas, borrando registros un día a la vez (aproximadamente 25,000 registros al día). Quiero poder ver esto mientras el proceso se ejecuta a través de declaraciones de impresión en la ventana de mensajes. Me gustaría poder ver un mensaje cada vez que se comprometa una eliminación de un día. ¿Hay alguna manera de hacer algo como esto? El procedimiento está definido más o menos a cabo de esta manera:Servidor Sql imprimir filas afectadas durante el ciclo 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 

Respuesta

20

Desafortunadamente, la producción instrucción PRINT se pone en cola y no se escribe en la salida inmediatamente. Una manera alrededor de esto es utilizar RAISERROR así:

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

Específicamente para lo que quiere:

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 

que también tienden a incluir la hora actual en el mensaje para que pueda registrar el progreso contra el tiempo.

+0

Esto funciona, pero todavía no estoy muy seguro de cómo agarrar el número de filas afectadas por la eliminar durante cada lote. ¿Alguna idea sobre eso? – Kevin

+1

@Kevin - Ver mi actualización :) – AdaTheDev

+0

¡Gracias! Esto funciona :) – Kevin

2

¿Algo más complejo que seleccionar @@ rowcount?

+0

¡Agradable y no complejo! – alfadog67

0

¿Qué le parece usar la cláusula OUTPUT? ¿Puedes escribir en la consola de SQL Server desde tu proceso almacenado?

Como en un disparador, tiene una pseudo-tabla "Eliminada" en sus manos, que contiene las filas que se están eliminando, con todas sus columnas.

WHILE EXISTS(<query statement>) 
BEGIN 
    BEGIN TRAN 

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

    COMMIT 

END 
+0

No necesariamente quiero ver cada fila que se eliminó por lote, sino solo el recuento total de ellas. No estoy seguro de que pueda obtener esa funcionalidad con la cláusula OUTPUT. – Kevin

+0

Puede dirigir la SALIDA en una tabla temporal y luego contar las filas en esa tabla temporal después del bucle WHILE. –

0

que solía hacer algo similar a esto, y debido a las impresiones en impresión diferida hasta que no era mucho uso, sin embargo he descubierto que la utilidad de línea de comandos osql salidas de inmediato, por lo que escribió el procedimiento almacenado y lo llamó de un archivo por lotes, lo que me permite ver el progreso.

0

Haz lo siguiente:

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)) 

Si desea validar, se puede tirar en el siguiente código.

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

Advertencia: Si la base de datos puede afectar las filas mientras esto sucede, es posible que vea discrepancias.

0

que podría hacer algo como esto para iterar sobre cada fila

  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 
Cuestiones relacionadas