这个查询是如何停止的?

时间:2012-01-27 17:10:13

标签: sql tsql

我正在看this query ,我对一些事情感到困惑。

-- T-SQL large update table
USE tempdb;
SELECT * INTO SOD
FROM AdventureWorks2008.Sales.SalesOrderDetail
GO
--(121317 row(s) affected)

-- SQL update in batches of 10,000
WHILE (2 > 1)
  BEGIN
    BEGIN TRANSACTION
    UPDATE TOP ( 10000 ) SOD
    SET    UnitPriceDiscount = 0.08,
           ModifiedDate = CONVERT(DATETIME,CONVERT(CHAR(10),getdate(),112))
    WHERE  ModifiedDate < CONVERT(DATETIME,CONVERT(CHAR(10),getdate(),112))

    IF @@ROWCOUNT = 0
      BEGIN
        COMMIT TRANSACTION
         BREAK
      END
    COMMIT TRANSACTION
    -- 1 second delay
    WAITFOR DELAY '00:00:01'
  END -- WHILE
GO

/* Messages

(10000 row(s) affected)

(10000 row(s) affected)

(10000 row(s) affected)

(10000 row(s) affected)

(10000 row(s) affected)

(10000 row(s) affected)

(10000 row(s) affected)

(10000 row(s) affected)

(10000 row(s) affected)

(10000 row(s) affected)

(10000 row(s) affected)

(10000 row(s) affected)

(1317 row(s) affected)

(0 row(s) affected)
*/
-- Cleanup
DROP TABLE SOD
GO

------------
  1. 是否正在制作临时表? SELECT * INTO SOD如果真的需要这个吗?我可以只使用while部分及以下部分吗?
  2. IF @@ROWCOUNT = 0如何变为零?它会自我增量还是什么?
  3. 修改

    这就是我现在所拥有的,但我仍然认为有无穷无尽的循环或其他东西

    BEGIN TRAN
    
    declare
      @rows_updated int ,
      @rowCount int,
      @batch_size   int
      set @rows_updated = -1
      set @batch_size   = 10000
      set @rowCount = 0;
    
    Declare @xx VARCHAR(20) DECLARE @length INT
    SET @length = 17 SET @xx = 'XXXXXXXXXXXXXXXX'
    
    while ( @rows_updated != 0 )
      begin
        update top(@batch_size)  myTbl
        SET myNumber = SUBSTRING(@xx, 0, @length - len(RIGHT(myNumber, 4))) + RIGHT(myNumber, 4) 
        WHERE myDate <'2011-Jan-02' 
        set @rows_updated = @@rowcount
       set @rowCount += 10000
        print @rowCount
      end
    
    ROLLBACK
    

    我做了一次计数

    select count(*) from myTbl
    where  myDate < '2011-Jan-02' 
    

    这会带回1,448,982

    的计数

    我得到的最后一次打印是31,110,000

    修改2

    我添加了这个,现在它停止但它仍然不是100%它应该在

    while (Select Count(*) From myTbl Where myDate  <'2011-Jan-02' ) >=  @rowCount
    

    编辑3

    我认为编辑2只是一遍又一遍地做同样的10,000行。

4 个答案:

答案 0 :(得分:2)

  1. SOD是由SELECT ... INTO语句创建的新表,请参阅here
  2. 当前@@ROWCOUNT语句不再更新任何记录时,或者换句话说,UPDATE表中的所有记录都已更新时,
  3. SOD变为0。
  4. 编辑修正了第一个答案

答案 1 :(得分:1)

提供的脚本执行以下操作:

  • 创建/加载永久表SOD

  • while(true)

    • 开始交易
    • 最多更新10,000行SOD表,其中修改日期小于当前日期,将单价折扣设置为0.08并将修改日期设置为当前日期。
    • 提交交易
    • 如果没有修改行,则退出循环
    • 重复

首先,正常安装SQL Server时不需要begin transactioncommit transaction,除非您通过执行IMPLICIT_TRANSACTIONS明确更改了SET IMPLICIT_TRANSACTIONS ON设置,其中如果BEGIN TRANSACTION语句不可用。原因是默认情况下,SQL Server以自动提交模式运行,因此每个语句都会触发, sotto voce ,成功时commit或失败时rollback。< / p>

此外,逻辑有点笨重。我会写这样的循环:

declare
  @rows_updated int ,
  @batch_size   int

set @rows_updated = -1
set @batch_size   = 10000

while ( @rows_updated != 0 )
  begin

    update top @batch_size SOD
    set UnitPriceDiscount = 0.08 ,
        ModifiedDate      = convert(datetime,convert(char(10),getdate(),112))
    where ModifiedDate    < convert(datetime,convert(char(10),getdate(),112))

    set @rows_updated = @@rowcount

  end

这可能会让事情变得更加透明。

答案 2 :(得分:0)

它不是临时表,SELECT ... INTO SOD FROM ...正在创建SalesOrderDetail表的精确副本(数据和模式)。表SOD在此语句之前不能存在,否则SQL Server将抛出错误。与临时表不同,SOD会一直持续到DROP TABLE运行。临时表仅在创建进程ID的持续时间内存在(或者,因为您在tempdb中创建表,它将在下次SQL Server重新启动时消失。)

如果最后一个DML语句没有影响行,

@@rowcount将为零。换句话说,当没有更新行时,@@rowcount将为零并突破无限循环。

答案 3 :(得分:0)

它正在AdventureWorks2008.Sales.SalesOrderDetail中复制tempdb。然后,UPDATE SOD10000一次记录@@ROWCOUNT。这是在表很大时完成的,因为较小的事务更快完成,从而减少了对表的争用。

除非指定SET ROWCOUNT OFF,否则

SOD在任何DML语句之后在内部更新。所以最终,SOD将没有任何合格记录,也不会更新任何记录,这将结束循环。

由于{{1}}最终被抛弃,整件事似乎毫无意义。所以,除非这段代码更多,否则我无法理解为什么要制作,更新,然后删除副本。