21

ジェイコブは完璧な質問をしました:構文を教えてくださいMERGE.

そこにあるすべての答えは、彼らが考えることができる最も複雑なケースにすぐにジャンプします。余分な混乱で構文がわかりにくくなります。

マークは答えました

MERGE 
   member_topic AS target
USING 
   someOtherTable AS source
ON 
   target.mt_member = source.mt_member 
   AND source.mt_member = 0 
   AND source.mt_topic = 110
WHEN MATCHED THEN 
   UPDATE SET mt_notes = 'test'
WHEN NOT MATCHED THEN 
   INSERT (mt_member, mt_topic, mt_notes) VALUES (0, 110, 'test')
; 

この答えを見て、私はジェイコブと同じくらい混乱しています:

私は someOtherTable を持っていません

Marc は、これsomeOtherTableはダミーのプレースホルダー値であると提案しました。そのテーブルがなくてもかまいません。

試してみると、SQL Server文句を言う

オブジェクト名「someOtherTable」が無効です。

それが重要でない場合(実際に重要であることを除いて) 、 USINGinUSING fooが何のためにあるのかを理解するのに苦労しています。

SQL Server 2008 MERGE 構文を使用しているときにfooUSINGを使用しているときは何を使​​用していますか?


ボーナス質問

MERGE を使用した UPSERT 構文とは:

IF (rowExists)
   UPDATE Users SET Firstname='Ian', LastName='Boyd' WHERE Username='iboyd'
ELSE
   INSERT INTO Users (UserGUID, Username, FirstName, LastName, AuthenticationMethod)
   VALUES ('{77410DC5-7A3E-4F1A-82C6-8EFB3068DE66}', 'iboyd', 'Ian', 'Boyd', 'Windows')

になります(私が試した正確なコード):

begin transaction

    MERGE 
       Users
    USING 
       foo
    ON  
       Users.UserName = foo.UserName
    WHEN MATCHED THEN
        UPDATE SET Firstname = foo.FirstName, Lastname = foo.LastName
    WHEN NOT MATCHED THEN
        INSERT (UserGUID, Username, FirstName, LastName, AuthenticationMethod)
        VALUES ('{77410DC5-7A3E-4F1A-82C6-8EFB3068DE66}', 'iboyd', 'Ian', 'Boyd', 'Windows')
    ; --A MERGE statement must be terminated by a semi-colon (;).

rollback

Msg 208, Level 16, State 1, Line 3
Invalid object name 'foo'.

?

Users列を含むテーブルの場合:

UserGUID uniqueidentifier
Username varchar(50)
FirstName varchar(50)
LastName varchar(50)
AuthenticationMethod varchar(50)

アップデート:

USING <table_source> 

どこtable_sourceにある:

table_or_view_name [ [ AS ] table_alias ] [ <tablesample_clause> ] 
    [ WITH ( table_hint [ [ , ]...n ] ) ] 
| rowset_function [ [ AS ] table_alias ] 
    [ ( bulk_column_alias [ ,...n ] ) ] 
| user_defined_function [ [ AS ] table_alias ]
| OPENXML <openxml_clause> 
| derived_table [ AS ] table_alias [ ( column_alias [ ,...n ] ) ] 
| <joined_table> 
| <pivoted_table> 
| <unpivoted_table> 

どこjoined_tableにある:

未定義

どこpivoted_tableにある:

未定義

どこunpivoted_tableにある:

未定義

4

3 に答える 3

17

マージには、テーブルソーステーブルとターゲットテーブルがあります。これにより、ソーステーブルが導入されます(実際の物理テーブルである必要はなく、結果セットのみである必要があります)。

文法はあなたの質問に示されています。別のテーブルまたはビューからマージするには、

MERGE 
   Users
USING SomeOtherTableName AS foo /*Alias is optional*/
ON /* ... */

<unpivoted_table>または、たとえばを使用できます

MERGE 
   Users
USING master..spt_values
UNPIVOT (X FOR Y IN ([high],[low])) AS foo 
ON  
   Users.Username = foo.Y 
WHEN MATCHED THEN
    UPDATE SET FirstName = foo.Y
WHEN NOT MATCHED THEN
    INSERT (UserGUID, Username, FirstName, LastName, AuthenticationMethod)
    VALUES (foo.Y, foo.Y, foo.Y, foo.Y, foo.Y);

ボーナスの質問についてVALUESは、オプションの一部としてここの条項を使用できderived_tableます。

MERGE Users
USING (VALUES ('{77410DC5-7A3E-4F1A-82C6-8EFB3068DE66}',
      'iboyd',
      'Ian',
      'Boyd',
      'Windows')) AS foo(UserGUID, Username, FirstName, LastName, AuthenticationMethod)
ON Users.UserName = foo.UserName
WHEN MATCHED THEN
  UPDATE SET Firstname = foo.FirstName,
             Lastname = foo.LastName
WHEN NOT MATCHED THEN
  INSERT (UserGUID,
          Username,
          FirstName,
          LastName,
          AuthenticationMethod)
  VALUES (UserGUID,
          Username,
          FirstName,
          LastName,
          AuthenticationMethod); 
于 2012-06-26T21:35:56.183 に答える
6

ソース テーブルは、次のように何でもかまいません。

MERGE 
   member_topic AS target
USING 
   (SELECT @Variable1, @Variable2, @Variable3) AS source(Col1, Col2, Col3)
ON 
   target.mt_member = source.Col1 
   AND source.Col1 = 0 
   AND source.Col2 = 110
WHEN MATCHED THEN 
   UPDATE SET mt_notes = 'test'
WHEN NOT MATCHED THEN 
   INSERT (mt_member, mt_topic, mt_notes) VALUES (0, 110, 'test');

明らかに、ネストされたソース選択では、さらに多くのことができます。ビュー、関数、テーブル変数、CTE イベントから選択します。

おまけの質問に関しては、あなたはあなた自身の質問に答えました。

非常に大きなテーブルの場合ROWLOCK、ターゲット テーブルでヒントを使用して、少なくとも更新時にテーブル全体をロックしないようにすることがあります。

MERGE 
   member_topic WITH (ROWLOCK) AS target

おまけの質問が機能しないことに関連して、これが機能するサンプルです。もちろん、いくつかのオブジェクトの名前を変更しました。

DECLARE @Variable1 AS INT;
SET @Variable1 = 1234;

MERGE dbo.Table1 WITH(ROWLOCK) target
USING(SELECT @Variable1) source(Key)
ON target.[Key] = source.[Key]
WHEN MATCHED THEN
    UPDATE SET
    Col1 = @SomeVar1,
    Col2 = @SomeVar2
WHEN NOT MATCHED THEN
INSERT 
        ([Key]
        ,[Col1]
        ,[Col2])
    VALUES
        (@Variable1
        ,@SomeVar1
        ,@SomeVar2);
于 2012-06-26T21:24:37.813 に答える
3

マーティン・スミスの答えに続いて、カンマで区切って括弧を繰り返すだけで、一度に複数の明示的な値の行をアップサートできます。

MERGE Users WITH (HOLDLOCK)
USING (VALUES ('{77410DC5-7A3E-4F1A-82C6-8EFB3068DE66}',
      'iboyd',
      'Ian',
      'Boyd',
      'Windows'),
      ('{00000DC5-7A3E-4F1A-82C6-8EF452D2DE66}',
      'jsmith',
      'John',
      'Smith',
      'ActiveDirectory')) AS foo(UserGUID, Username, FirstName, LastName, AuthenticationMethod)
ON Users.UserName = foo.UserName
WHEN MATCHED THEN
  UPDATE SET Firstname = foo.FirstName,
             Lastname = foo.LastName
WHEN NOT MATCHED THEN
  INSERT (UserGUID,
          Username,
          FirstName,
          LastName,
          AuthenticationMethod)
  VALUES (UserGUID,
          Username,
          FirstName,
          LastName,
          AuthenticationMethod); 

これを SQL Server 2012 でテストしました。 (これをコメントとして追加したはずですが、文字が多すぎます。)

これを見たHOLDLOCKを追加しました.UPSERTにMERGEを使用している場合、ポイントが確実にロックされているため、構文は確かに明確ではありません. 大きなテーブルの ROWLOCK に関する Marcel のコメントも参照してください。

平均よりも明確な別の投稿もありました。

于 2014-10-16T09:12:53.460 に答える