SQL Server中的MERGE命令

时间:2010-08-26 05:20:11

标签: sql sql-server-2008 merge insert

我一直在使用声明

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 个答案:

答案 0 :(得分:1)

我读过有关MERGE语句的所有内容都说明您需要为INSERT语句指定列。如果您正在寻找快速获取INSERT声明的方法,您可以右键单击SSMS中的表格并选择脚本表格 - >插入到 - >剪贴板。然后,您可以将其粘贴到查询中,并仅更改VALUES部分。

Merge statement

答案 1 :(得分:1)

我也是;我讨厌输入列名。

我通常在动态SQL中构建Merge语句 我有一个函数,它将一个表名作为参数,并返回一个字符串,其中包含使用表名前缀,[]括号和逗号正确格式化的所有列名,如S.Col1,S.Col2,S.Col3

我还可以告诉你,我使用所需的列构建临时表,并将临时表传递给我的函数,因为有时你不想要所有列的列表。但这可能是一个令人困惑的混淆,掩盖了重要的一点;

  1. 使用动态sql
  2. 使用函数创建csv列列表。

答案 2 :(得分:1)

在这种情况下使用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]