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

时间:2018-06-22 19:18:59

标签: sql sql-server

给出:

主表:

let str = 'hi i am jack'

str = arr.split(' ').map(word => `${word[0].toUpperCase()}${word.slice(1)}`).join(' ');

console.log(str) // 'Hi I Am Jack'

新行表:

A  B  C
a1 b1 NULL
a3 b2 NULL

所需的输出:

A  B  C
a1 b1 c1
a2 b2 c2

我需要一个查询,用于比较主表和New_Row表之间的每一列,如果该行中的所有其他列都相同,则更新主表行,或者如果该行中的其他列不同,则插入新行。

在上面的示例中,New_Row表中的第一行与主表中的第一行匹配,但NULL值除外(假定主表缺少此数据),因此在所需的输出中填充了c1。 New_Row表中的第二行与主表中的任何行都不匹配(因为主表中没有a3 b2行),因此它将作为新行插入到所需的输出中。

我将如何编写此查询?

2 个答案:

答案 0 :(得分:2)

SQL Server支持MERGE语句以在单个查询中执行INSERTUPDATEDELETE操作。

您可以在这里找到有关此声明的详细信息:https://docs.microsoft.com/en-us/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及更高版本中受支持。

答案 1 :(得分:2)

因此,在两个表中都没有唯一键的情况下,这有点麻烦,但仍然可行。您可以使用MERGE语句或显式事务来执行此操作。您使用哪一个主要取决于您。就我个人而言,我不是MERGE的忠实拥护者,因为我发现语法很笨拙,并且可能会有一些奇怪的行为,但这取决于您。另外,我不确定表上是否存在任何唯一约束,但是如果没有,并且有可能重复,那么您可能要避免使用MERGE,因为它在更新非约束时效果不佳-独特的数据集。

无论采用哪种方法,您还需要注意如何处理NULL值。如果您只是进行直接比较(例如t.c = s.c),而其中一列为空,则将从不评估为true(因为null从不等于任何东西;甚至另一个null)。如果您很在意这一点,则需要用占位符值替换空值(例如isnull(t.c, '') = isnull(s.c, ''),或者另外检查列是否为空值(例如(t.c is null or s.c is null or t.c = s.c) 设置数据

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