3

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

2 に答える 2

18

date現在、 、sipdipおよびで一致する値がない場合は、新しい値を挿入したいと考えていますが、条件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 キーワードは避けることをお勧めします。

于 2012-05-29T07:48:49.373 に答える
7

あなたの論理が間違っていると思います。

あなたのロジックは次のとおりです。

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 がどのように機能するか想像してみてください: ソースが空で、ターゲットが空ではありません。

MERGE2種類の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 }
}

2番、

[ WHEN NOT MATCHED BY SOURCE [ AND <clause_search_condition> ]
    THEN <merge_matched> ] [ ...n ]

つまり、ソースにペアがないターゲットのすべての行に対して、ターゲットで UPDATE または DELETE を実行できます。INSERT を実行する可能性はありません。

<merge_matched>::=
    { UPDATE SET <set_clause> | DELETE }

作品を作成MERGEするために、ソースを空にする必要はありません。あなたのソースはSELECTwithWHERE句なので、空のソースになる可能性があります。したがって、ある種の条件ロジックで空にならないようにし、一時テーブルまたはテーブル変数を使用するか、トリッキーな JOIN または UNION を使用する必要があります。その場合のアイデアをMERGEまったく捨てて、古典的な条件付きUPDATEorを実行することをお勧めしINSERTます。

于 2012-05-29T08:23:04.130 に答える