35

IDフィールドのあるテーブルがあるとします。レコードがまだ存在しない場合は、レコードを挿入したいと思います。次の例では、@Field1に格納されている値がテーブルにすでに存在するかどうかを確認します。そうでない場合は、新しいレコードを挿入します。

テーブルの定義:

MyTable (MyTableId int Identity not null, Field1 int not null, Field2 int not null)  

これは、値がすでに存在するかどうかを確認し、必要に応じて挿入する方法です。

merge MyTable as t
using (@Field1, @Field2) as s (Field1,Field2)
on (t.Field1=s.Field1)
when not matched then
    insert (Field1,Field2) values (s.Field1,s.Field2);

レコードがテーブルにまだ存在していなかったときにID値を取得するには、次を追加します。

output Inserted.MyTableId  

しかし、レコードがすでにテーブルにある場合(つまり、一致する場合)はどうなりますか?

私が見つけた唯一の方法は、Mergeステートメントを実行した後にテーブルをクエリすることです。

select MyTableId from MyTable where Field1=@Field1

マージから直接ID値を取得する方法はありますか?

4

3 に答える 3

35

レコードが既に存在する場合は、一致した ID を次のように変数に格納できます。

DECLARE @MatchedId INTEGER;

MERGE MyTable as t
....
....
WHEN MATCHED THEN
    UPDATE SET @MatchedId = t.MyTableId;

更新:
完全な例を次に示します。これは 1 つの方法を示しています。

DECLARE @UpdateVariable bit
DECLARE @ChangeResult TABLE (ChangeType VARCHAR(10), Id INTEGER)
DECLARE @Data TABLE (Id integer IDENTITY(1,1), Val VARCHAR(10))
INSERT @Data ([Val]) VALUES ('A');

MERGE @data AS TARGET
USING (SELECT 'A' AS Val UNION ALL SELECT 'B' AS Val) AS SOURCE ON TARGET.Val = SOURCE.Val
WHEN NOT MATCHED THEN
    INSERT ([Val])
    VALUES (SOURCE.Val)
WHEN MATCHED THEN 
    UPDATE SET @UpdateVariable = 1
OUTPUT $action, inserted.Id INTO @ChangeResult;

SELECT * FROM @data
SELECT * FROM @ChangeResult

注意点は次のとおりです。

  • $action は、行に対して実行されたアクションのタイプ (INSERT、UPDATE、DELETE) を示します。
  • @ChangeResult テーブルには、行われた変更の種類に関する情報が保持されます
  • WHEN MATCHED のケースでは、基本的にダミー変数を設定しています。これは、UPDATE パスが確実にヒットして出力に UPDATE 行が生成されるようにすること以外には、ここでは何の目的もありません。つまり、@UpdateVariable は他の目的には使用されません。実際に既存の行を更新したい場合は、ここに適切な UPDATE を入れますが、既存の行を実際に更新したくない場合は、この「ダミーの」更新が必要なようです。
于 2012-05-18T10:25:24.483 に答える
31

これは、代替のやや単純なアプローチです(私の意見では):

DECLARE @Id [int];

MERGE INTO [MyTable] AS [t]
USING (VALUES
  (@FieldA, @FieldB)
)
 AS [x] (FieldA, FieldB)
 ON [t].[FieldA] = [x].[FieldA]
AND [t].[FieldB] = [x].[FieldB]
WHEN NOT MATCHED BY TARGET THEN
    INSERT (FieldA, FieldB)
    VALUES (FieldA, FieldB)
WHEN MATCHED THEN
    UPDATE SET @Id = [t].[Id]

IF @Id IS NULL
BEGIN
    SET @Id = CAST(SCOPE_IDENTITY() as [int]);
END
SELECT @Id;

マージ ステートメントの結果が一致した場合@Id、一致する行の ID が設定されます。一致しない場合は、新しい行が挿入され、その新しい ID を から選択できるようになりますSCOPE_IDENTITY()

于 2015-07-23T05:09:38.890 に答える