簡體   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