【问题标题】:Is there a way to supress the "rows affected" messages in a T-SQL loop and still get other messages in realtime?有没有办法在 T-SQL 循环中抑制“受影响的行”消息并仍然实时获取其他消息?
【发布时间】:2014-08-07 21:41:30
【问题描述】:

我需要从 SQL Server 2008 R2 的大表中删除大部分记录。此表上有一个巨大的 DELETE 触发器,用于清理其他表。我需要批量运行删除,这样我才能看到它在做什么,所以我编写了一个循环来自动化批处理,但提供状态消息。我遇到的问题是,如果我在 DELETE 语句周围使用 SET NOCOUNT,它只会在循环完成后给我消息。我只是想要一种方法来抑制 DELETE 语句“受影响的行”消息,但仍然可以实时获取我的 PRINT 消息。我无法更改 DELETE 触发器。我真的只是希望它像@ECHO OFF 一样运行

DECLARE @counter INT;
DECLARE @rowstogo INT;
SET @rowstogo = ( SELECT COUNT(1) FROM Customer WHERE Attribute1 <> 11 );
SET @counter = 1;
--while @rowstogo > 0 
WHILE @counter<5  --Test of only 4 iterations
BEGIN
    PRINT 'Pass '+ CAST(@counter as varchar) +': '+ CAST(@rowstogo as varchar)+' records'
    SET NOCOUNT ON
    DELETE TOP (100) FROM Customer WHERE Attribute1 <> 11 
    SET NOCOUNT OFF
    SET @counter = @counter + 1
    SET @rowstogo = ( select COUNT(1) from Customer where Attribute1 <> 11 )
    PRINT CAST ( @rowstogo as varchar ) + ' records remaining'
    PRINT '--------------------------------'
END

【问题讨论】:

  • 而不是 PRINT 'foo'; 使用 RAISERROR('foo',0,1) WITH NOWAIT; - 您仍然可能会遇到奇怪的 SSMS 缓冲区问题,但它不应该经常发生。也不要打扰SET NOCOUNT OFF; - 总是有SET NOCOUNT ON;,句号。
  • 由于这是一个巨大的表,您可能会考虑更改您在循环中设置@rowstogo 的方式。这样的事情将消除每次循环遍历该表的需要。 SET @rowstogo = @rowstogo - @@rowcount
  • 我尝试了 SET @rowstogo = @rowstogo - @@rowcount,我认为它从删除触发器中获取了最后的行数并且给了我奇怪的结果。
  • 您知道自己一次做 100 次,请改用 SET @rowstogo -= 100。至于你原来的问题。您是否有可以在 SQL Server 之外执行此操作的程序员? VB或C#中的东西?他们可以为此创造更好的用户体验。
  • 这是我们的一位客户的数据清除/清理。唯一真正的用户是我。这个脚本将来可能会被重用,但它根本不是面向客户端的。我只需要一些方法来跟踪它在过程中的位置。 RaiseError 似乎运作良好。我添加了一个变量@NumberInBatch,这样我就不会与删除顶部 X 和 rowstogo-X 不同步。谢谢大家的帮助!

标签: sql sql-server while-loop


【解决方案1】:

假设您正在从 SSMS 运行查询。您可以使用全局临时表并使用单独的查询窗口来检查运行状态。

由于创建全局临时表并插入到全局临时表中,性能可能会受到一点影响。

    DECLARE @counter INT;
DECLARE @rowstogo INT;

if OBJECT_ID('tempdb.dbo.##rowtable') is not null
    drop table ##rowtable;

-- create global temp table
create table ##rowtable (txt varchar(1000))

SET @rowstogo = ( SELECT COUNT(1) FROM Customer WHERE Attribute1 <> 11 );
SET @counter = 1;
--while @rowstogo > 0 
WHILE @counter<5  --Test of only 4 iterations
BEGIN
    -- PRINT 'Pass '+ CAST(@counter as varchar) +': '+ CAST(@rowstogo as varchar)+' records'

    insert into ##rowtable
    select 'Pass '+ CAST(@counter as varchar) +': '+ CAST(@rowstogo as varchar)+' records'

    SET NOCOUNT ON
    DELETE TOP (100) FROM Customer WHERE Attribute1 <> 11 
    SET NOCOUNT OFF
    SET @counter = @counter + 1
    SET @rowstogo = ( select COUNT(1) from Customer where Attribute1 <> 11 )

        -- insert into global table
    insert into ##rowtable
    select CAST ( @rowstogo as varchar ) + ' records remaining'

    -- PRINT CAST ( @rowstogo as varchar ) + ' records remaining'
    -- PRINT '--------------------------------'
END

drop table ##rowtable;

在 SSMS 的单独查询窗口中

select * from ##rowtable

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-18
    • 2016-11-03
    • 1970-01-01
    • 1970-01-01
    • 2011-01-02
    • 1970-01-01
    • 2022-06-13
    • 1970-01-01
    相关资源
    最近更新 更多