我正在尝试使用MERGE命令插入或更新单个表,但是我总是得到“0行受影响”。我的目标很简单:如果存在更新,否则插入。我做错了什么?
注意:表的主键是组合键= [date] + sip + dip + port 其中date是datetime,所有其他字段都是int
merge iplog as t
using (SELECT * from iplog Where [date]='20120101' and sip=1 and dip=2 and port=80) as s
on t.[date]=s.[date] and t.sip=s.sip and t.dip=s.dip and t.port=s.port
when matched then
update set t.size=t.size+s.size
when not matched then
insert values ('20120101',1,2,80,1);
答案 0 :(得分:9)
我认为如果date
,sip
,dip
和port
目前没有匹配,我想要插入新值,但目前还不清楚在UPDATE
条件下您想要的大小。我选择了1:
create table iplog (
[date] date not null,
sip int not null,
dip int not null,
port int not null,
size int not null
)
GO
merge iplog as t
using (SELECT '20120101' as [date] , 1 as sip , 2 as dip , 80 as port) as s
on t.[date]=s.[date] and t.sip=s.sip and t.dip=s.dip and t.port=s.port
when matched then
update set t.size=t.size+1 --What should this be?
when not matched then
insert values ('20120101',1,2,80,1);
select * from iplog
你会注意到源码现在根本没有引用目标表。
附注 - 我建议避免使用date
之类的SQL关键字作为列名。
答案 1 :(得分:6)
我猜你的逻辑错了。
你的逻辑是:
if source is empty* then insert my row
*
时来源为空SELECT '20120101' as [date] , 1 as sip , 2 as dip , 80 as port
返回0行..
所以实际上你正在尝试将目标与空源合并。这是逻辑错误。
你应该写这样的东西
IF EXISTS(SELECT * from iplog Where [date]='20120101' and sip=1 and dip=2 and port=80)
BEGIN
UPDATE
iplog
SET
t.size=t.size+1
WHERE
[date]='20120101' and sip=1 and dip=2 and port=80
END
ELSE
BEGIN
INSERT INTO iplog VALUES ('20120101',1,2,80,1)
END
<强>更新强> 想象一下MERGE的工作原理: 你有空源而不是空目标。
MERGE
可以有两种WHEN NOT MATCHED
子句
首先,
[ WHEN NOT MATCHED [ BY TARGET ] [ AND <clause_search_condition> ]
THEN <merge_not_matched> ]
这意味着对于源中没有成对的每一行,您可以执行INSERT到目标。因此,如果您有空源,则无法进行任何INSERT
。
<merge_not_matched>::=
{
INSERT [ ( column_list ) ]
{ VALUES ( values_list )
| DEFAULT VALUES }
}
其次,
[ WHEN NOT MATCHED BY SOURCE [ AND <clause_search_condition> ]
THEN <merge_matched> ] [ ...n ]
这意味着对于目标中没有成对的目标中的每一行,您可以在目标上执行UPDATE或DELETE。没有可能做INSERT。
<merge_matched>::=
{ UPDATE SET <set_clause> | DELETE }
要使MERGE
适合您,您无需使用源代码。您的来源为SELECT
且带有WHERE
子句,因此可能会成为空来源。因此,您应该使用某种编码逻辑将其设置为非空,使用一些临时表或表变量或棘手的JOIN或UNION ..但这样您的代码可能会变得不可读。在这种情况下,最好放弃MERGE
的想法并执行经典条件UPDATE
或INSERT
。