65.9K
CodeProject 正在变化。 阅读更多。
Home

对一个非常大的表进行批量更新

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.12/5 (7投票s)

2006年1月24日

2分钟阅读

viewsIcon

92660

在生产环境中更新超大表,避免锁定整个表。

我们这些在生产/实时数据库中工作的人,都知道在超大表上运行更新查询的痛苦。这非常成问题,因为它会导致以下情况:

  • 锁升级:整个表将被您的应用程序锁定,因此其他用户/应用程序将无法对此表执行 DDL 操作
  • TempDB 将变得巨大
  • 对表的 更新锁 将阻止其他用户对表进行更改

我写了一个下面的代码片段,它将帮助我们解决上述问题

-- 步骤 1: 声明变量

使用 DBNAME
声明 @counter int
声明 @RowsEffected int
声明 @RowsCnt int
声明 @CodeId int
声明 @Err int
SELECT @COUNTER = 1
SELECT @RowsEffected = 0

 


/*
步骤 2: 获取我们需要更新现有代码的代码值。在我的情况下,我从一个表中获取它,我们总是可以硬编码它。
*/


SELECT @CodeID = CodeID FROM CODE WHERE XXXX ='YYYY'


/*
步骤 3: 开始 while 循环,如果我们有 100,000 条记录,并且在每个循环中更新 5,000 条记录,因此总循环次数将是 100,000/5000,即 20
*/

WHILE ( @COUNTER > 0)
BEGIN
SET ROWCOUNT 5000


-- 注意: SET ROWCOUNT 5000 只会选择前 5000 条记录 */

   
      /*更新表 */
  UPDATE Table
SET CodeID= @CodeID
WHERE Codeid = @OldCode
SELECT @RowsCnt = @@ROWCOUNT ,@Err = @@error
IF @Err <> 0
BEGIN
打印 '更新记录时出现问题'
END
IF @RowsCnt = 0
SELECT @COUNTER = 0
ELSE

/* 增加计数器 */

 SELECT @RowsEffected = @RowsEffected + @RowsCnt
打印 '受影响的总行数:'+convert(varchar,@RowsEffected)

            /*延迟循环 10 秒,以便更新完成*/    

    等待延迟 '00:00:10'        
 END


--步骤 4: 检查是否所有记录都已更新。 IF EXISTS ( SELECT CodeID
FROM Table (NOLOCK)
WHERE CodeID = @OldCodeid
)
BEGIN
打印 ('并非所有记录都已更新,存在一些问题,请联系开发人员')
END
BEGIN
打印 ('所有记录已成功更新!!!!')
END
/* ------将行计数设置为默认值 ----*/
SET ROWCOUNT 0

 

 

 

 

 

 


 

© . All rights reserved.