Ian*_*oyd 20 sql-server merge upsert sql-server-2008-r2
雅各布问了一个完美的问题:给我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')
;
Run Code Online (Sandbox Code Playgroud)
看着这个答案,我和雅各布一样困惑:
我没有someOtherTable
Marc建议这someOtherTable是一个虚拟的占位符值 - 没有那个表并不重要.
我尝试了,SQL Server 确实抱怨
无效的对象名称'someOtherTable'.
这使我努力理解什么USING的USING foo是对,如果它不是重要的(除了实际上很重要).
是什么USING时,它的使用使用富时我使用SQL Server 2008合并语法?
什么是使用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')
Run Code Online (Sandbox Code Playgroud)
变成(我试过的确切代码):
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'.
Run Code Online (Sandbox Code Playgroud)
?
使用
Users包含列的表:Run Code Online (Sandbox Code Playgroud)UserGUID uniqueidentifier Username varchar(50) FirstName varchar(50) LastName varchar(50) AuthenticationMethod varchar(50)
更新:
USING <table_source>
Run Code Online (Sandbox Code Playgroud)
在哪里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>
Run Code Online (Sandbox Code Playgroud)
在哪里joined_table:
未定义
在哪里pivoted_table:
未定义
在哪里unpivoted_table:
未定义
Mar*_*ith 16
合并具有表源和目标表.这引入了源表(不一定是实际的物理表,只是结果集).
语法在你的问题中表明.要从另一个表或视图合并使用
MERGE
Users
USING SomeOtherTableName AS foo /*Alias is optional*/
ON /* ... */
Run Code Online (Sandbox Code Playgroud)
或者你可以使用<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);
Run Code Online (Sandbox Code Playgroud)
对于您的奖金问题,您可以使用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);
Run Code Online (Sandbox Code Playgroud)
源表可以是任何内容,例如:
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');
Run Code Online (Sandbox Code Playgroud)
显然,在嵌套源代码中你可以做更多的事情.从视图,函数,表变量,CTE中选择均匀.
至于奖金问题,你回答了自己的问题.
有时候,对于非常大的表,我也使用ROWLOCK目标表上的提示,至少在更新的情况下尽量不要锁定整个表:
MERGE
member_topic WITH (ROWLOCK) AS target
Run Code Online (Sandbox Code Playgroud)
与奖金问题无关,这是一个工作样本.当然,我重命名了一些对象.
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);
Run Code Online (Sandbox Code Playgroud)