web-dev-qa-db-ja.com

MS SQLを使用して更新および注文する方法

理想的にはこれをやりたい:

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

英語:DBから上位10個の利用可能な(status = 0)メッセージを取得し、それらをロックします(status = 10)。優先度の高いメッセージを最初に取得する必要があります。

残念ながら、MS SQLでは、更新でorder by句を使用できません。

とにかくこれを回避する方法は?

49
Toad

サブクエリを実行して、最初に上位10個のIDを優先度順に並べ替えてから、そのサブクエリにあるIDを更新できます。

UPDATE  messages 
SET status=10 
WHERE ID in (SELECT TOP (10) Id 
             FROM Table 
             WHERE status=0 
             ORDER BY priority DESC);
43
Eduardo Crimi
WITH    q AS
        (
        SELECT  TOP 10 *
        FROM    messages
        WHERE   status = 0
        ORDER BY
                priority DESC
        )
UPDATE  q
SET     status = 10
99
Quassnoi

私はこれをより良いアプローチとして提供しなければなりません-あなたは常にアイデンティティ分野の贅沢を持っているわけではありません:

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

サブクエリを必要なだけ複雑にすることもできます-複数のテーブルの結合など。

なぜこれが良いのですか? messagesテーブル内のIDフィールド(またはその他の一意の列)の存在に依存しません。テーブルに一意のキーがまったくない場合でも、任意のテーブルの上位N行を更新するために使用できます。

4
mfascino
UPDATE messages SET 
 status=10 
WHERE ID in (SELECT TOP (10) Id FROM Table WHERE status=0 ORDER BY priority DESC);
1
dotjoe

以下のコメントで述べているように、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)