Sql server 使用具有相同源的SQL Server合并命令(&);目标表

Sql server 使用具有相同源的SQL Server合并命令(&);目标表,sql-server,merge,Sql Server,Merge,我试图使用MERGE命令插入或更新一个表,但是我总是得到一个“0行受影响”。我的目标很简单:如果存在更新,否则插入。我做错了什么 注意:表的主键是组合键=[date]+sip+dip+端口 其中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]

我试图使用MERGE命令插入或更新一个表,但是我总是得到一个“0行受影响”。我的目标很简单:如果存在更新,否则插入。我做错了什么

注意:表的主键是组合键=[date]+sip+dip+端口 其中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);

如果当前没有一个与
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关键字作为列名。

我猜您的逻辑是错误的

你的逻辑是:

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
在不匹配时可以有两种
子句

首先,

[ WHEN NOT MATCHED [ BY TARGET ] [ AND <clause_search_condition> ]
        THEN <merge_not_matched> ]
第二,

[ WHEN NOT MATCHED BY SOURCE [ AND <clause_search_condition> ]
    THEN <merge_matched> ] [ ...n ]
[当源不匹配时[和]
然后][…n]
这意味着对于目标中的每一行,如果源代码中没有一对,则可以在目标上执行更新或删除操作。不可能做插入

<merge_matched>::=
    { UPDATE SET <set_clause> | DELETE }
::=
{更新集|删除}

要使
MERGE
适合您,您不需要使用empy源代码。您的源代码是带有
WHERE
子句的
SELECT
,因此它可能成为空源代码。因此,您应该使用某种编码逻辑使其非空,使用一些临时表或表变量或复杂的联接或并集。。但这样一来,您的代码可能会变得不可读。在这种情况下,最好放弃
MERGE
的想法,然后执行经典的条件
UPDATE
INSERT

当您的目标是“不匹配时”,目标表如何成为源表?这到底意味着什么?我计划在一个过程中使用它,比如:InsertOrUpdate(DateTime.Date,sourceIP,DestIP,Port,PacketSize)。因此,如果respetive记录存在,它将增加数据包大小,否则将插入一个带有值的新记录。这是可能的吗?当然可以用MERGE实现,但首先不需要空的源代码,如表格变量、临时表、公共表表达式,但要填充源代码表,还需要某种条件逻辑。合并非常有用,但它不适合任何地方。
<merge_not_matched>::=
{
    INSERT [ ( column_list ) ] 
        { VALUES ( values_list )
        | DEFAULT VALUES }
}