理想情况下,我想这样做:
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 子句。
无论如何如何规避这个?
理想情况下,我想这样做:
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 子句。
无论如何如何规避这个?
WITH q AS
(
SELECT TOP 10 *
FROM messages
WHERE status = 0
ORDER BY
priority DESC
)
UPDATE q
SET status = 10
您可以执行子查询,首先获取按优先级排序的前 10 个 ID,然后更新该子查询中的 ID:
UPDATE messages
SET status=10
WHERE ID in (SELECT TOP (10) Id
FROM Table
WHERE status=0
ORDER BY priority DESC);
我必须将此作为一种更好的方法提供 - 你并不总是拥有身份字段的奢侈:
UPDATE m
SET [status]=10
FROM (
Select TOP (10) *
FROM messages
WHERE [status]=0
ORDER BY [priority] DESC
) m
您还可以根据需要使子查询变得复杂 - 加入多个表等......
为什么这样更好?它不依赖于表中是否存在标识字段(或任何其他唯一列)messages
。它可用于更新任何表的前 N 行,即使该表根本没有唯一键。
UPDATE messages SET
status=10
WHERE ID in (SELECT TOP (10) Id FROM Table WHERE status=0 ORDER BY priority DESC);
如以下评论中所述,您还可以使用 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)