I'm using the MERGE
statement to upsert rows in an sql server 2008 database. However, my sproc is a single-row operation, whereas in fact I'd prefer to batch these. Is this even possible and, if so, how do I do it?
views:
99answers:
2
+3
A:
Can you use Table-Valued Parameters in your proc? Take a look here http://www.sommarskog.se/arrays-in-sql-2008.html#TVP_in_TSQL to get some ideas
Then in the proc you can use MERGE against the TVP
SQLMenace
2010-05-27 19:02:04
A:
i have created a proc called 'upsert' which takes a source table name, target table name, fields to join on, and fields to update (fields are separated by commas) and then does the merge dynamically.
code is below.
CREATE proc [common].[upsert](@source nvarchar(100), @target nvarchar(100), @join_field nvarchar(100), @fields nvarchar(200))
as
--@source is the table name that holds the rows that you want to either update or insert into @target table
--@join_field is the 1 field on which the two tables will be joined...you can only join on 1 field right now!
--@fields are the comma separated fields that will either be updated or inserted into @target. They must be the same name in @source and @target
declare @sql nvarchar(max)
set @sql = '
merge '+ @target +' as target
using '+ @source +' as source
on target.'+ @join_field +' = source.'+ @join_field +'
when matched then
update set
' + common.upsert_update_fields_string_builder('source', 'target', @fields) + '
when not matched then
insert ('+ @join_field +', '+ @fields +')
values (source.'+ @join_field +',' + common.upsert_insert_fields_string_builder('source', @fields) +');
'
exec(@sql)
CREATE function [common].[upsert_insert_fields_string_builder](@source nvarchar(100), @fields nvarchar(200))
returns nvarchar(1000)
as
begin
declare @string nvarchar(max)
select @string = coalesce(
@string + ',' + @source + '.' + items,
@source +'.' + items)
from common.split_string(@fields,',')
return @string
end
CREATE function [common].[upsert_update_fields_string_builder](@source nvarchar(100), @target nvarchar(100), @fields nvarchar(200))
returns nvarchar(1000)
as
begin
declare @string nvarchar(max)
select @string = coalesce(
@string + ', '+ @target + '.' + items + '=' + @source + '.' + items,
''+ @target +'.' + items + '='+ @source +'.' + items)
from common.split_string(@fields,',')
return @string
end
thomas
2010-05-28 00:45:28
Yeah, it would be great to take a look. Please post a link if you can - thanks.
Dmitri Nesteruk
2010-05-28 06:38:02
just edited the answer to include the code. hope it works for you! i have found it useful on many occasions.
thomas
2010-05-28 18:02:33