繁体   English   中英

SQL Server-如果新插入行; 更新(如果存在)

[英]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语句以在单个查询中执行INSERTUPDATEDELETE操作。

您可以在此处找到有关此语句的详细信息: 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM