2012-05-29 4 views
1

Я пытаюсь вставить или обновить одну таблицу с помощью команды MERGE, однако я всегда получаю «0 строк, затронутых». Моя цель проста: если существует обновление, иначе вставьте. Что я делаю не так?Использование команды SQL Server MERGE с той же исходной и целевой таблицей

Примечание: первичный ключ таблицы является комбинированный ключ = [дата] + глотка + падение + порт где дата даты и времени, а все остальные поля 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

Как целевой стол может быть источником, когда вы нацеливаетесь на «когда не соответствует»? Что бы это значило? –

ответ

7

Я думаю, что Вы желаете, чтобы вставить новое значение, если в настоящее время нет одного совпадения по 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 

Вы заметите, что исходный код вообще не ссылается на целевую таблицу.


Примечание стороны - я бы рекомендовал избегать SQL ключевых слов, таких как date как имена столбцов.

+0

Я планирую использовать это в процедуре, подобной: InsertOrUpdate (DateTime.Date, sourceIP, DestIP, Port, PacketSize). Итак, если существует сигнальная запись, она увеличит размер пакета, иначе вставьте новую запись со значениями. – meraydin

5

Я предполагаю, что вы ошибаетесь.

Ваша логика:

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 

UPDATE: Представьте, как MERGE работы: У вас есть пустой источник и не пустой цели.

MERGE может иметь два вида WHEN NOT MATCHED положений

Во-первых,

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

Это означает, что для каждой строки в источнике без пары на цели, которую вы можете сделать вставку в цель. Поэтому, если у вас есть пустой источник, нет никаких причин делать 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, вам не нужен источник empy. Ваш источник равен SELECT с предложением WHERE, поэтому он может стать пустым источником.Поэтому вы должны сделать его непустым с какой-то кодирующей логикой, использовать временную таблицу или таблицу varialble или сложный JOIN или UNION .. Но таким образом ваш код может стать нечитаемым для вас. Лучше отказаться от идеи MERGE в этом случае вообще и сделать классический условный UPDATE или INSERT.

+0

Это то, что я хочу сделать, но с командой MERGE. Это возможно? – meraydin

+0

Конечно, вы можете сделать это с помощью MERGE, но сначала вам не нужно пустого источника, как табличная переменная, временная таблица, общее табличное выражение - но для заполнения исходной таблицы вам нужна какая-то условная логика. MERGE очень полезен, но он не подходит повсюду. – huhu78

Смежные вопросы