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 syntax with extraneous confusion.
Marc gave an answer:
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')
;
Looking at this answer, i am as confused as Jacob was:
I don't have a someOtherTable
Marc suggested that someOtherTable
is a dummy placeholder value - it doesn't matter that you don't have that table.
i try it, and SQL Server does complain
Invalid object name 'someOtherTable'.
That leaves me struggling to understand what the USING
in USING foo
is for if it's not important (except actually important).
What is USING
using when it's using foo when i use SQL Server 2008 MERGE syntax?
What is the UPSERT syntax using MERGE:
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')
becomes (exact code i tried):
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'.
?
With a
Users
table that contains the columns:UserGUID uniqueidentifier Username varchar(50) FirstName varchar(50) LastName varchar(50) AuthenticationMethod varchar(50)
Update:
USING <table_source>
Where table_source
is:
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>
Where joined_table
is:
undefined
Where pivoted_table
is:
undefined
Where unpivoted_table
is:
undefined
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);