4

Update: I am using Sql Server 2008 R2.

I am going to update a large number of rows and to avoid unnecessary locking I will do this in matches of around a thousand lines per update.

Using SET ROWCOUND I can limit the update to 1000 lines and using WHERE ID > x I can set which batch it should run.

But for this to work I need to know the highest ID from the just processed batch.

I could user OUTPUTto return all affected ID's and find the highest one on code but I would like to be able to return just the highest ID.

I tried this

SELECT MAX(id) 
FROM (
    UPDATE mytable
    SET maxvalue = (SELECT MAX(salesvalue) FROM sales WHERE cid = t.id GROUP BY cid)
    OUTPUT inserted.id
    FROM mytable t
    WHERE au.userid > 0
) updates(id)

But it gives me this error A nested INSERT, UPDATE, DELETE, or MERGE statement is not allowed in a SELECT statement that is not the immediate source of rows for an INSERT statement.

BUT if I try to insert the result into a table directly it is valid

CREATE TABLE #temp(id int)

INSERT INTO #temp
SELECT MAX(id) 
FROM (
    UPDATE mytable
    SET maxvalue = (SELECT MAX(salesvalue) FROM sales WHERE cid = t.id GROUP BY cid)
    OUTPUT inserted.id
    FROM mytable t
    WHERE au.userid > 0
) updates(id)

drop table #temp

Is there any workaround to this and can anyone explain why I can insert the result into a table but not just return the result?

4

1 回答 1

3

正如 BOL 所说,不要为此(或根本)使用 SET ROWCOUNT:

使用 SET ROWCOUNT 不会影响 SQL Server 下一版本中的 DELETE、INSERT 和 UPDATE 语句!

不要在新的开发工作中将 SET ROWCOUNT 与 DELETE、INSERT 和 UPDATE 语句一起使用,并计划修改当前使用它的应用程序。此外,对于当前使用 SET ROWCOUNT 的 DELETE、INSERT 和 UPDATE 语句,我们建议您重写它们以使用 TOP 语法。

您也可以使用表变量来执行此操作:

DECLARE @Log TABLE (id INT NOT NULL);

UPDATE TOP 1000 mytable
SET maxvalue = (SELECT MAX(salesvalue) FROM sales WHERE cid = t.id GROUP BY cid)
OUTPUT inserted.id INTO @Log
FROM mytable t
WHERE au.userid > 0

SELECT maxid = MAX(id)
FROM @Log
于 2013-05-17T10:30:09.747 回答