2010-12-02 6 views
4

私は基本的にUPSERTを行うためにMERGEステートメントを使用しています。宛先に存在しない行については、それらを特定の順序で挿入したいと思います。残念ながら、ORDER BY句はマージ・ステートメントではサポートされていないようです。ある声明でこれを行う方法はありますか?私がやろうとしています何の良いアイデアのための例を参照してください:SQL Server 2008 MERGEステートメントに不一致行が挿入される順序を指定できますか?

CREATE TABLE #destination (ident int not null identity(1,1), id int not null, value int not null) 
INSERT INTO #destination (id,value) VALUES (1,50) 

CREATE TABLE #source (id int not null, value int not null) 
INSERT INTO #source (id,value) VALUES (1,100),(3,300),(2,200) 

MERGE #destination d 
USING #source s 
    ON d.id = s.id 
WHEN MATCHED THEN 
    UPDATE 
    SET d.value = s.value 
WHEN NOT MATCHED THEN 
    INSERT (id,value) 
    VALUES (s.id,s.value); 

SELECT * FROM #destination ORDER BY ident 
/* 
WILL LIKELY SEE: 
    1, 1, 100 
    2, 3, 300 
    3, 2, 200 
WANT TO ACHIEVE: 
    1, 1, 100 
    2, 2, 200 
    3, 3, 300 
*/ 

私はこれをしたい理由は、私はこのマージを行い、自分のコードのためのユニットテストを書いて、決定論的に挿入をしたいしたいです注文。私はこれを回避する方法があることを知っていますが、MERGEの挿入を注文する方法があれば、最も簡単です。

答えて

2

だから今これはできません。 documentation on MERGEから、挿入、削除、および更新の操作は順不同です。それはそれでTOPがそれをどのように影響するかの説明です埋め込まれた部分ました:

TOP句は、さらに、指定された 値とインサートに結合された行の 数を減らし、更新、または アクションを削除 に適用されます残りの行は順不同で の形式で結合されます。つまり、 には、WHEN 句で定義されたアクション の間に行が分散する順序はありません。たとえば、TOP (10)を指定すると10行に影響します。これらの行のうち、7 が更新され、3が挿入されるか、または1 が削除され、5が更新され、4 が挿入されるなどがあります。

+0

あなたの見積もりは、行の順序がないことをかなり明確にしていますが、操作については不思議です。少なくとも2つの例では、更新は挿入前に行われます。したがって、操作が同じ順序で実行されている可能性がありますか?削除、更新、そして挿入?これに影響を与える方法はありますか? –

1

あなたのケースではこれが受け入れられるかどうかはわかりませんが、SET IDENTITY_INSERTを使用してID列を上書きして注文を保証することができます。

CREATE TABLE #destination (ident int not null identity(1,1), id int not null, value int not null) 
INSERT INTO #destination (id,value) VALUES (1,50) 

CREATE TABLE #source (id int not null, value int not null) 
INSERT INTO #source (id,value) VALUES (1,100),(3,300),(2,200) 

SET IDENTITY_INSERT #destination ON 

MERGE #destination d 
USING #source s 
    ON d.id = s.id 
WHEN MATCHED THEN 
    UPDATE 
    SET d.value = s.value 
WHEN NOT MATCHED THEN 
    INSERT (ident,id,value) 
    VALUES (s.id, s.id, s.value); 

SET IDENTITY_INSERT #destination OFF 

SELECT * FROM #destination ORDER BY ident 
+0

この例では、私の例はidと等しいidを持つ単純なものだからです。しかし、ID列が連続していても保証されていない同一または連続ID列が必要な場合、その列は分解されます。言い換えれば、私が注文したい全理由は、私がアイデンティティ列について心配する必要がないためです。 – Zugwalt

関連する問題