57

理想情况下,我想这样做:

UPDATE TOP (10) messages SET status=10 WHERE status=0 ORDER BY priority DESC;

In English: 我想从数据库中获取前 10 条可用 (status=0) 消息并锁定它们 (status=10)。优先级更高的消息应该首先得到。

不幸的是,MS SQL 不允许在更新中使用 order by 子句。

无论如何如何规避这个?

4

5 回答 5

118
WITH    q AS
        (
        SELECT  TOP 10 *
        FROM    messages
        WHERE   status = 0
        ORDER BY
                priority DESC
        )
UPDATE  q
SET     status = 10
于 2009-03-17T16:37:02.663 回答
50

您可以执行子查询,首先获取按优先级排序的前 10 个 ID,然后更新该子查询中的 ID:

UPDATE  messages 
SET status=10 
WHERE ID in (SELECT TOP (10) Id 
             FROM Table 
             WHERE status=0 
             ORDER BY priority DESC);
于 2009-03-17T16:35:43.867 回答
7

我必须将此作为一种更好的方法提供 - 你并不总是拥有身份字段的奢侈:

UPDATE m
SET [status]=10
FROM (
  Select TOP (10) *
  FROM messages
  WHERE [status]=0
  ORDER BY [priority] DESC
) m

您还可以根据需要使子查询变得复杂 - 加入多个表等......

为什么这样更好?它不依赖于表中是否存在标识字段(或任何其他唯一列)messages。它可用于更新任何表的前 N ​​行,即使该表根本没有唯一键。

于 2016-07-06T14:14:35.230 回答
2
UPDATE messages SET 
 status=10 
WHERE ID in (SELECT TOP (10) Id FROM Table WHERE status=0 ORDER BY priority DESC);
于 2009-03-17T18:42:24.593 回答
0

如以下评论中所述,您还可以使用 SET ROWCOUNT 子句,但仅适用于 SQL Server 2014 及更早版本。

SET ROWCOUNT 10

UPDATE messages
SET status = 10 
WHERE status = 0 

SET ROWCOUNT 0

更多信息:http: //msdn.microsoft.com/en-us/library/ms188774.aspx

或使用临时表

DECLARE @t TABLE (id INT)
INSERT @t (id)
SELECT TOP 10 id
FROM messages
WHERE status = 0
ORDER BY priority DESC

UPDATE messages
SET status = 10
WHERE id IN (SELECT id FROM @t)
于 2009-03-17T16:44:00.057 回答