Вопрос по merge – Пример слияния T SQL, необходимый для понимания

38

Следующие:

MERGE dbo.commissions_history AS target
USING (SELECT @amount, @requestID) AS source (amount, request)
ON (target.request = source.request)
WHEN MATCHED THEN
    UPDATE SET amount = source.amount
WHEN NOT MATCHED THEN
    INSERT (request, amount)
    VALUES (source.request, source.amount);

отhttps://stackoverflow.com/a/2967983/857994 довольно изящный способ сделать вставку / обновление (и удалить с некоторой дополнительной работой). Мне трудно следить, хотя даже после некоторого поиска в Google.

Может кто-нибудь, пожалуйста:

  • explain this a little in simple terms - the MSDN documentation mutilated my brain in this case.
  • show me how it could be modified so the user can type in values for amount & request instead of having them selected from another database location?

По сути, я хотел бы использовать это для вставки / обновления из приложения C # информации, взятой из XML-файлов, которые я получаю. Итак, мне нужно понять, как я могу сформулировать запрос вручную, чтобы получить мои проанализированные данные в базу данных с помощью этого механизма.

Я дал пошаговое руководство ниже, но на вашем месте я бы опубликовал второй вопрос здесь о SO, который имеет структуру вашей целевой таблицы и образец фрагмента из вашего xml-источника, и спросил ... как бы я написал оператор MERGE для обновления эта таблица из этого XML. Также имейте в виду, что заявление MERGE в конце может даже не быть лучшим инструментом для работы. RThomas
Спасибо, это было как раз то, что мне было нужно. Я могу ответить на дополнительный вопрос позже, хотя это хорошее предложение. John Humphreys - w00te

Ваш Ответ

2   ответа
72

присоединиться к заявлениям тогда вам нужно начать. Понимание того, как объединяет работу, является ключом к остальному. Как только вы ознакомитесь с объединениями, понять слияние проще всего, если рассматривать его как полное объединение с инструкциями о том, что делать для строк, которые соответствуют или не совпадают.

Итак, используя предоставленный пример кода, давайте посмотрим на таблицу Commissions_history.

|  Amount  |   Request  |   <other fields> |
--------------------------------------------
|  12.00   |   1234     |   <other data>   |
|  14.00   |   1235     |   <other data>   |
|  15.00   |   1236     |   <other data>   |

Оператор слияния создает полное объединение между таблицами, которое называется & quot; target & quot; и выражение, которое возвращает таблицу (или набор результатов, который по логике очень похож на таблицу, подобную CTE), называемую «источником».

В приведенном примере он использует переменные в качестве источника, который, как мы предполагаем, был установлен пользователем или передан в качестве параметра.

DECLARE @Amount Decimal = 18.00;
DECLARE @Request Int = 1234;

MERGE dbo.commissions_history AS target       
USING (SELECT @amount, @requestID) AS source (amount, request)       
ON (target.request = source.request)   

Создает следующий набор результатов, когда рассматривается как объединение.

|  Amount  |   Request  |   <other fields> | Source.Amount | Source.Request  |
------------------------------------------------------------------------------
|  12.00   |   1234     |   <other data>   |   18.00       |     1234        |
|  14.00   |   1235     |   <other data>   |   null        |     null        |
|  15.00   |   1236     |   <other data>   |   null        |     null        |

Использование инструкций о том, что делать с целью при условии, что совпадение найдено.

WHEN MATCHED THEN        
UPDATE SET amount = source.amount    

Результирующая таблица целей теперь выглядит следующим образом. Строка с запросом 1234 обновлена до 18.

|  Amount  |   Request  |   <other fields> |
--------------------------------------------
|  18.00   |   1234     |   <other data>   |
|  14.00   |   1235     |   <other data>   |
|  15.00   |   1236     |   <other data>   |

Так как совпадение БЫЛО найдено, больше ничего не происходит. Но допустим, что значения из источника были такими.

DECLARE @Amount Decimal = 18.00;
DECLARE @Request Int = 1239;

Результирующее соединение будет выглядеть так:

|  Amount  |   Request  |   <other fields> | Source.Amount | Source.Request  |
------------------------------------------------------------------------------
|  12.00   |   1234     |   <other data>   |   null        |     null        |
|  14.00   |   1235     |   <other data>   |   null        |     null        |
|  15.00   |   1236     |   <other data>   |   null        |     null        |
|  null    |   null     |   null           |   18.00       |     1239        |

Поскольку соответствующая строка не была найдена в цели, оператор выполняет другое предложение.

WHEN NOT MATCHED THEN                                 
INSERT (request, amount)                                 
VALUES (source.request, source.amount);  

В результате получается целевая таблица, которая теперь выглядит следующим образом:

|  Amount  |   Request  |   <other fields> |
--------------------------------------------
|  12.00   |   1234     |   <other data>   |
|  14.00   |   1235     |   <other data>   |
|  15.00   |   1236     |   <other data>   |
|  18.00   |   1239     |   <other data>   |

Истинный потенциал операторов слияния возможен, когда источником и целью являются большие таблицы. Так как он может делать большое количество обновлений и / или вставок для каждой строки с помощью одного простого оператора.

Последнее замечание Важно помнить, чтоnot matched по умолчанию полное предложениеnot matched by targetОднако вы можете указатьnot matched by source вместо или в дополнение к предложению по умолчанию. Оператор слияния поддерживает оба типа несоответствия (записи в источнике не в цели, или записи в цели не в источникеas defined by the on clause). Вы можете найти полную документацию, ограничения и полный синтаксис на MSDN.

Отличный ответ, спасибо!
Отличный ответ, очень тщательный. Мне нравится всегда указывать либо «a TARGET» или «по источнику»; с предложением WHEN NOT MATCHED, потому что он более понятен при повторном чтении. Вам не нужно запоминать значение по умолчанию, и оно ближе к английскому.
FULL JOIN могу делать классные вещи!
0

В приведенном примере ответа вы сделали

DECLARE @Request Int

, но вызывая его в SQL следующим образом:

SELECT @amount, @requestID

Другой будет называть и называть переменные одинаково

@amount vs. Amount -> @Amount & Amount

Похожие вопросы