IF EXISTS 和 MERGE 语句

Posted

技术标签:

【中文标题】IF EXISTS 和 MERGE 语句【英文标题】:IF EXISTS and MERGE Statement 【发布时间】:2022-01-02 11:29:34 【问题描述】:

我有数据从多个其他表流入一个表让我们说:Table_A 然后我有一个合并存储过程,它从表 A 中获取数据并将其与表 B 合并。

但是,似乎有些不对劲。如果我截断并加载数据,它工作正常,但如果我不截断和加载,并且只是每小时获取查询,我会收到错误消息

消息 8672,级别 16,状态 1,过程 Merge_Table_A,第 4 行 [批处理开始第 0 行] MERGE 语句多次尝试更新或删除同一行。当目标行匹配多个源行时会发生这种情况。 MERGE 语句不能多次 UPDATE/DELETE 目标表的同一行。优化 ON 子句以确保目标行最多匹配一个源行,或使用 GROUP BY 子句对源行进行分组。

我该如何克服这个问题?

我希望能够增量加载数据而不是截断加载,但同时有一个存储过程,可以更新或插入或不关心行是否已存在。

【问题讨论】:

你能提供你的示例代码和数据吗? 您对错误消息和解决方案有何困惑?您不能有多个与目标记录匹配的源记录,因此您需要合并您的源记录,以便在执行合并之前每个匹配的“键”只有一条记录 【参考方案1】:

您的目标表中似乎有重复行,这些行是从您之前的运行中加载的。

注意:Merge 中的匹配不考虑在运行 Merge 时插入(甚至重复)的行。

下面是我的带有示例数据的复制示例:

表1:初始数据

表 2:目标表

合并声明

MERGE tb2 AS Target
USING tb1   AS Source
 ON Source.firstname = Target.firstname and 
    Source.lastname = Target.lastname 

-- For Inserts
WHEN NOT MATCHED BY Target THEN
INSERT (firstname, lastname, updated_date) 
VALUES (Source.firstname, Source.lastname, source.updated_date)

-- For Updates
WHEN MATCHED THEN UPDATE SET
   Target.updated_date      = Source.updated_date

-- For Deletes
WHEN NOT MATCHED BY Source THEN
DELETE;

执行 Merge 时,它​​会插入所有数据而没有任何错误。

tb1 中的新数据:

当我运行 Merge 语句时,它给了我和你一样的错误。

作为一种解决方法,使用以下选项之一,

    如果可能,在 ON 子句中添加附加条件以唯一标识数据。

    从源中删除重复项并将数据合并到 tb2 中,如下所示。

     --temp table
     drop table if exists #tb1;
    
     select *  into #tb1 from (
         select *, row_number() over(partition by firstname, lastname order by firstname, lastname, updated_date desc) as rn from tb1) a
     where rn = 1 
    
     MERGE tb2 AS Target
     USING #tb1 AS Source
      ON Source.firstname = Target.firstname and 
         Source.lastname = Target.lastname 
    
     -- For Inserts
     WHEN NOT MATCHED BY Target THEN
     INSERT (firstname, lastname, updated_date) 
       VALUES (Source.firstname, Source.lastname, source.updated_date)
    
     -- For Updates
     WHEN MATCHED THEN UPDATE SET
        Target.updated_date     = Source.updated_date
    
     -- For Deletes
     WHEN NOT MATCHED BY Source THEN
       DELETE;
    

数据合并到tb2成功。

【讨论】:

以上是关于IF EXISTS 和 MERGE 语句的主要内容,如果未能解决你的问题,请参考以下文章

在 SQL 语句中使用 'If Exists' 两次

oracle insert if not exists 语句

47.__if_not_exists语句

非常基本的 IF EXISTS 语句不起作用

避免多个 if exists, else if exits 用于内部使用的不同连接的语句

2022-11-21:第N高的薪水。表结构和数据的sql语句如下。请问sql语句如何写? DROP TABLE IF EXISTS employee; CREATE TABLE employee (