What is USING in SQL Server 2008 MERGE syntax?

后端 未结 3 1668
借酒劲吻你
借酒劲吻你 2020-12-14 08:12

Jacob asked the perfect question: give me the MERGE syntax.

Every answer out there immediately jumps to the most complicated case they can think of; obscuring the sy

相关标签:
3条回答
  • 2020-12-14 08:42

    Source table can be anything, such as:

    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');
    

    Obviously, in the nested source select you can do many more things. Select from a view, a function, a table variable, a CTE even.

    As for the bonus question, you answered your own question.

    Sometimes,for very large tables, I also use the ROWLOCK hint on the target table, to at least try not to lock the entire table in case of updates:

    MERGE 
       member_topic WITH (ROWLOCK) AS target
    

    Related to the bonus question not working, here's a working sample. I renamed some of the objects, of course.

    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);
    
    0 讨论(0)
  • 2020-12-14 08:54

    A merge has a table source and a target table. This introduces the source table (which need not be an actual physical table, just a result set).

    The grammar is indicated in your question. To merge from another table or view use

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

    Or you can use <unpivoted_table> for example

    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);
    

    For your bonus question you can use the VALUES clause here as part of the derived_table option.

    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); 
    
    0 讨论(0)
  • 2020-12-14 08:59

    Following on from Martin Smith's answer, you can upsert several explicit value rows at once simply by repeating the brackets, separating with a comma, eg,

    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); 
    

    Tested this on SQL Server 2012. (Would have added this as a comment but too many characters.)

    I added a HOLDLOCK having seen this, because if you're using MERGE for UPSERT surely the point is locking, the syntax is certainly no clearer. See also Marcel's comment on ROWLOCK for large tables.

    There was another post I found clearer than average, too.

    0 讨论(0)
提交回复
热议问题