[英]SQL Server - Insert row if new; Update if exists
鉴于:
主表:
A B C
a1 b1 NULL
a3 b2 NULL
新行表:
A B C
a1 b1 c1
a2 b2 c2
所需输出:
A B C
a1 b1 c1
a2 b2 c2
a3 b2 NULL
我需要一个查询来比较主表和New_Row表之间的每一列,如果该行中的所有其他列相同,则更新主表行,或者如果该行中的其他列不同,则插入新行。
在上面的示例中,New_Row表中的第一行与主表中的第一行匹配,但NULL值除外(假定主表缺少此数据),因此在所需的输出中填充了c1。 New_Row表中的第二行与主表中的任何行都不匹配(因为主表中没有a3 b2行),因此它将作为新行插入到所需的输出中。
我将如何编写此查询?
SQL Server支持MERGE
语句以在单个查询中执行INSERT
, UPDATE
或DELETE
操作。
您可以在此处找到有关此语句的详细信息: https : //docs.microsoft.com/zh-cn/sql/t-sql/statements/merge-transact-sql
MERGE [master_table] AS TARGET
USING [new_row_table] AS SOURCE
ON (TARGET.A = SOURCE.A) AND (TARGET.B = SOURCE.B)
WHEN MATCHED THEN
UPDATE SET TARGET.C = SOURCE.C
WHEN NOT MATCHED BY TARGET THEN
INSERT (A, B, C)
VALUES (SOURCE.A, SOURCE.B, SOURCE.C);
一个警告MERGE
仅在SQL Server 2008及更高版本中受支持。
因此,在两个表中都没有唯一键的情况下,这有点麻烦,但仍然可行。 您可以使用MERGE
语句或显式事务来执行此操作。 您使用哪一个主要取决于您。 我个人不是MERGE
忠实MERGE
因为我发现语法很笨拙,并且可能会有一些奇怪的行为,但这取决于您。 另外,我不知道如果有什么在桌子上(一个或多个)存在惟一性约束,但如果没有,并且复制是可能的,你可能希望避免MERGE
,因为它不与更新非唯一的数据集发挥很好。
无论采用哪种方法,您都需要注意如何处理NULL
值。 如果您只是进行直接比较(例如tc = sc
),并且其中一列为null,则该值将永远不会作为true进行评估(因为null
永远不等于任何东西;甚至另一个null
)。 如果您对此很在意,则需要用占位符值替换空值(例如, isnull(tc, '') = isnull(sc, '')
或者另外检查该列是否为空(例如(tc is null or sc is null or tc = sc)
设置数据
if object_id('tempdb.dbo.#New') is not null drop table #Master
create table #Master
(
a varchar(10),
b varchar(10),
c varchar(10)
)
if object_id('tempdb.dbo.#new') is not null drop table #new
create table #new
(
a varchar(10),
b varchar(10),
c varchar(10)
)
insert into #master
values ('a1', 'b1', null), ('a2', 'b2', null)
insert into #new
values ('a1', 'b1', 'c1'), ('a2', 'b2', 'c2')
方法1:合并
merge into #master t -- target
using #new s --source
on t.a = s.a
and t.b = s.b
and t.c = s.c
when not matched by target then insert
(
a,
b,
c
)
values
(
s.a,
s.b,
s.c
)
when matched then update
set c = s.c;
方法2:显式事务
begin tran
update t
set c = s.c
from #master t -- target
inner join #new s -- source
on t.a = s.a
and t.b = s.b
and t.c = s.c
insert into #master
(
a,
b,
c
)
select
s.a,
s.b,
s.c
from #new s -- source
left outer join #master t --target
on s.a = t.a
and s.b = t.b
and s.c = t.c
where t.a is null
commit tran
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.