SQL Merge со вставкой в ​​другую таблицу

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

MERGE Assets AS target
USING (@id, @name)FROM Sales AS source (id, name) ON (target.id = SOURCE.id)
WHEN MATCHED THEN 
    UPDATE SET target.Status = @status, target.DateModified = SYSUTCDATETIME()
WHEN NOT MATCHED THEN 
    INSERT INTO @tableVar (id, name, status, dateModified)  
    VALUES (@id, @name, @status, SYSUTCDATETIME())

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


person iLemming    schedule 22.02.2012    source источник


Ответы (2)


Вы просто не можете этого сделать. MERGE работает только с двумя таблицами — исходной и целевой.

Для вашего требования вам нужно, например. используйте CTE (Common Table Expression), чтобы найти строки, которые не совпадают, и вставьте их в третью таблицу.

Что-то типа:

;WITH NonMatchedData AS
(
   -- adapt this as needed - just determine which rows match your criteria,
   -- and make sure to return all the columns necessary for the subsequent INSERT
   SELECT (columns)
   FROM dbo.SourceTable
   WHERE ID NOT IN (SELECT DISTINCT ID FROM dbo.TargetTable)
)
INSERT INTO dbo.ThirdTable(Col1, Col2, ....., ColN)
  SELECT Col1, Col2, ....., ColN
  FROM NonMatchedData
person marc_s    schedule 22.02.2012
comment
Есть ли альтернатива NOT IN в этом случае? Что-то вроде JOIN, которое перенастраивает все строки, которые не удалось выполнить JOIN? Кроме LEFT JOIN + IS NULL. Кроме того, действительно ли необходим CTE? Разве он не может INSERT INTO ThirdTable FROM SELECT NonMatchedData? - person Alexandre; 22.02.2012
comment
@PeekaySwitch: конечно, но тогда вы ДЕЙСТВИТЕЛЬНО выполняете LEFT OUTER JOIN и проверяете, что столбец из dbo.TargetTable является NULL .... Я не вижу другого варианта, правда .... - person marc_s; 22.02.2012
comment
Знаете ли вы на макушке, что предлагает лучшую производительность? Я ожидаю, что LEFT OUTER JOIN будет более эффективным, но, возможно, они расположены близко друг к другу, я просто всегда старался избегать использования NOT IN с огромным количеством данных в Where (например, идентификаторы). - person Alexandre; 22.02.2012
comment
@PeekaySwitch: стандартный ответ: это зависит от обстоятельств! — однозначного ответа нет. Это зависит от размера таблиц, количества строк, того, какие индексы у вас есть ...... в основном, если такая производительность является для вас проблемой / проблемой: попробуйте их оба, измерьте их, сравните выполнение планы - посмотрите, какой из них лучше для вас. Я не могу сказать это отсюда, не зная ваших данных и ваших дел.... - person marc_s; 22.02.2012
comment
Ха-ха, хорошо! Огромное спасибо, что нашли время ответить на некоторые мои вопросы! Я все еще ломаю голову над CTE и T-SQL в целом! Приятно общаться с людьми, разбирающимися в T-SQL! - person Alexandre; 22.02.2012
comment
Что ж, кажется, вы можете сделать это. Другой ответ отлично сработал для меня. - person Andrew; 12.04.2018

Вы МОЖЕТЕ сделать это очень легко...

Вы можете поместить оператор MERGE в INSERT INTO FROM:
http://technet.microsoft.com/en-us/library/bb510625.aspx#sectionToggle2

-OR-

Вы можете сделать это непосредственно в операторе слияния:

Быстрый пример:

WHEN NOT MATCHED THEN
    DELETE
OUTPUT Deleted.* INTO dbo.MyTable;

Это вставит несоответствия в вашу существующую целевую таблицу. Вы можете использовать v-таблицы Updated, Inserted, Deleted для направления данных в другие места.

person nm1984    schedule 24.12.2012
comment
Это должно быть в предложении MATCHED или NOT MATCHED BY SOURCE, но оно помогает. - person John Eisbrener; 24.07.2017
comment
Это фактический ответ, и за него следует больше голосовать. Так просто и приятно. - person Andrew; 12.04.2018
comment
Может ли кто-нибудь аннотировать быстрый пример с небольшими подробностями о том, почему это работает? например, является ли ВЫВОД частью DELETE или частью MERGE? - person Be Kind To New Users; 19.05.2018
comment
@MichaelPotter OUTPUT является частью MERGE. Посмотрите синтаксис в документации. Вы ищете ‹output_clause› docs.microsoft.com/en-us/sql/t-sql/statements/ - person thebitguru; 28.05.2018
comment
Пример для первой версии был бы хорош вместо простой ссылки, особенно потому, что эта ссылка автоматически ведет к самой новой версии SQL Server, а не к той OP, которая изначально предназначалась для ссылки. - person bugybunny; 30.01.2019