T-SQL 的 RowNum(不是 TOP #)

mar*_*ate 2 sql-server t-sql update

试图运行更新,但我想逐步完成它,因为它有相当多的数据并且不想一次全部爆炸。

在 oracle 中,选择我想要的行要容易一些,因为您可以将它包含在WHERE子句中,但在 T-SQL 中您将它包含在select. 我想写一些类似的东西:

Update Instances
set thing = 'new thing'
Where rownum<500
Run Code Online (Sandbox Code Playgroud)

基本上想一次做500个,这个语法在TSQL中可行吗?

McN*_*ets 6

看看关于它的MS Docs

限制和限制

当 TOP 与 INSERT、UPDATE、MERGE 或 DELETE 一起使用时,引用的行没有按任何顺序排列,并且不能在这些语句中直接指定 ORDER BY 子句。如果需要使用 TOP 以有意义的时间顺序插入、删除或修改行,则必须将 TOP 与在 subselect 语句中指定的 ORDER BY 子句一起使用。请参阅本主题后面的示例部分。

UPDATE TOP(500) instances
SET thing = 'new thing'
WHERE Something = 'SomethingElse';
Run Code Online (Sandbox Code Playgroud)

或者

UPDATE instances
SET thing = 'new thing'
FROM (SELECT TOP (500) Id
      FROM instances
      ORDER BY Something) AS t1
WHERE instances.Id = t1.Id;
Run Code Online (Sandbox Code Playgroud)

或者您可以直接更新派生表而无需连接:

UPDATE t1
SET thing = 'new thing'
FROM (SELECT TOP (500) *
      FROM instances
      ORDER BY Something) AS t1;
Run Code Online (Sandbox Code Playgroud)

这种方法的一个例子可以在dbfiddle找到。


Han*_*non 5

您可以使用SET ROWCOUNT xxx来限制受更新语句影响的行数。

像这样的东西:

SET ROWCOUNT 500;

WHILE EXISTS (SELECT 1 FROM Instances WHERE thing = 'new thing')
BEGIN
    BEGIN TRANSACTION;
    UPDATE Instances
    SET thing = 'new thing'
    WHERE thing <> 'new thing';
    COMMIT TRANSACTION;
    CHECKPOINT;
    WAITFOR DELAY '00:00:01'; --wait one second between loops
END
Run Code Online (Sandbox Code Playgroud)

如果您的数据库配置为简单恢复模式,则不需要大量日志空间。但是,如果您的数据库处于完全恢复模式,您可能希望在此期间定期进行日志备份。

微软文档SET ROWCOUNT提醒,这是一个过时的设置:

使用 SET ROWCOUNT 不会影响 SQL Server 未来版本中的 DELETE、INSERT 和 UPDATE 语句。在新的开发工作中避免将 SET ROWCOUNT 与 DELETE、INSERT 和 UPDATE 语句一起使用,并计划修改当前使用它的应用程序。对于类似的行为,请使用 TOP 语法。

话虽如此,此时它不在已删除功能列表中。