Команда MERGE в SQL Server - PullRequest
       7

Команда MERGE в SQL Server

1 голос
/ 26 августа 2010

Я использовал утверждение

insert into target 
select * from source 
where [set of conditions] for a while.

Недавно нашел эту команду MERGE, которую будет более эффективно использовать для моих целей, чтобы я мог изменить приведенное выше выражение на

MERGE target 
USING source ON [my condtion] 
WHEN NOT MATCHED BY TARGET 
THEN INSERT VALUES (source.col1, source.col2, source.col3) 

Но проблема для меня, скажем, если у меня более 20 столбцов в исходной таблице, я должен перечислить все из них, мне нужен способ указать его для вставки источника. *. Есть ли способ? Я новичок в SQL. Ценю твою помощь.

Заранее спасибо:)

Ответы [ 3 ]

1 голос
/ 26 августа 2010

Я тоже;Я ненавижу печатать имена столбцов.

Я обычно строю оператор Merge в динамическом SQL.
У меня есть функция, которая принимает имя таблицы в качестве параметра и возвращает строку, содержащую все имена столбцов, отформатированные должным образом с помощью таблицыПрефикс имени, [] скобки и запятая, как в S.Col1, S.Col2, S.Col3

Я также могу сказать, что я создаю временную таблицу с необходимыми столбцами и передаювременная таблица для моей функции, потому что иногда вам не нужен список всех столбцов.Но это, вероятно, было бы запутанным дураком, скрывающим важные биты;

  1. Использование динамического sql
  2. Использование функции для создания списка столбцов csv.
1 голос
/ 01 сентября 2010

В этой ситуации просто нет преимущества использования MERGE. Зачем слишком усложнять? Придерживайтесь принципа KISS, для chrissake.

В любом случае, вот сценарий:

declare 
    @targetTableName varchar(100) = 'target'
    ,@targetSchemaName varchar(20) = 'dbo'
    ,@sourceTableName varchar(100) = 'source'
    ,@sourceSchemaName varchar(20) = 'dbo2'
    ,@matchCondition varchar(50) = 't.id = s.id'
    ,@columns varchar(max)

set @columns = (select ','+quotename(c.name)
from sys.tables t 
join sys.columns as c on t.object_id = c.object_id
join sys.schemas s on s.schema_id = t.schema_id
where t.name = @targetTableName and s.name = isnull(@targetSchemaName, s.name)
for xml path(''))

--a column name starts with a comma

declare @sql varchar(max) =  '
merge @target t 
using @source s on @matchCondition
when not matched then 
insert (@columns)
values @sourceColumns'

set @sql = 
replace(replace(replace(replace(replace(@sql
, '@matchCondition', @matchCondition)
 --replace @columns with column list with the first comma removed
, '@columns', stuff(@columns, 1, 1, ''))
--replace @sourceColumns with column list with the 's.' prefix and comma removed
, '@sourceColumns', stuff(replace(@columns, ',', ',s.'),1,1,''))
, '@target', quotename(@targetSchemaName)+'.'+quotename(@targetTableName))
, '@source', quotename(@sourceSchemaName)+'.'+quotename(@sourceTableName))

print @sql
--exec(@sql)

И мы получим что-то вроде этого:

merge [dbo].[target] t 
using [dbo2].[source] s on t.id = s.id
when not matched then 
insert ([column1], [column2], [column3], [column4])
values s.[column1], s.[column2], s.[column3], s.[column4]
1 голос
/ 26 августа 2010

Все, что я прочитал относительно оператора MERGE, говорит о том, что вам нужно указать столбцы для вашего оператора INSERT.Если вы ищете быстрый способ получить оценку INSERT, вы можете щелкнуть правой кнопкой мыши таблицу в SSMS и выбрать Script Table As-> INSERT To-> Clipboard.Затем вы можете вставить это в свой запрос и изменить только часть VALUES.

Оператор слияния

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...