我有一个基于文件的import thingy,用户可以在其中发布要导入数据库的文件。插入新记录并更新包含已存在Id的记录。
发布文件后 ID NAME 5傻傻的
他们可以通过发布新文件来纠正这个问题 ID NAME 5莎莉
我将该文件的批量插入(C#windows服务)放入批量表(Sql Server Azure v12)。这些文件可以包含数百万行,所以我想避免遍历行。批量插入后,我有一个SP,它执行合并更新/插入并更新已存在的行并插入新的行。
我遇到的问题是当用户在同一文件中发布新记录和更正同一记录时。我在目标牌桌上得到了一个主要的违规行为。
有解决这个问题的好方法吗?
以下是一个例子:
--drop table #bulk
--drop table #target
create table #bulk(
id int,
name varchar(10)
)
insert into #bulk values (1,'John')
insert into #bulk values (2,'Sally')
insert into #bulk values (3,'Paul')
insert into #bulk values (4,'Gretchen')
insert into #bulk values (5,'Penny')
insert into #bulk values (5,'Peggy')
create table #target(
id int not null,
name varchar(10),
primary key (id))
merge #target as target
using(select id, name from #bulk) as bulktable
on target.id = bulktable.id
when matched then update
set target.name = bulktable.name
when not matched then
insert(id, name) values (bulktable.id, bulktable.name);
答案 0 :(得分:1)
这将处理名称的最新值。
您需要为#bulk
创建一个新的创建脚本CREATE TABLE #bulk
(
row_id int identity(1,1),
id int,
name varchar(10)
)
这是可以与新批量表一起使用的脚本:
;WITH CTE as
(
SELECT
id, name,
row_number() over (partition by id order by row_id desc) rn
FROM #bulk
), CTE2 as
(
SELECT id, name
FROM CTE
WHERE rn = 1
)
MERGE #target as target
USING CTE2 as bulktable
on target.id = bulktable.id
WHEN matched and
not exists(SELECT target.name except SELECT bulktable.name)
-- this will handle null values. Otherwise it could simply have been:
-- matched and target.name <> bulktable.name
THEN update
SET target.name = bulktable.name
WHEN not matched THEN
INSERT(id, name) VALUES (bulktable.id, bulktable.name);