【问题标题】:Multiple Update Statement in SQL Server MERGE [duplicate]SQL Server MERGE中的多个更新语句[重复]
【发布时间】:2014-11-08 23:45:25
【问题描述】:

SQL Server 版本:Microsoft SQL Server 2012 - 11.0.2218.0 (x64)

运行此查询时出现以下异常。 例外:“WHEN MATCHED”类型的操作不能在 MERGE 语句的“UPDATE”子句中出现多次。

我知道该异常不止一次出现在 Merge 语句中的 Update 语句中。 您能否建议我如何实现以下 SQL 查询逻辑?

基于一列,
如果匹配且列不为空,则仅更新一个不同的列。
当匹配且列为空时,更新大部分列。
不匹配时插入。

完整的SQL是

MERGE TargetTable AS targetT 
USING   SourceTable AS sourceT ON sourceT.Npi = targetT.Npi
WHEN    MATCHED AND IsNull(targetT.SPI, '') <> '' THEN
        UPDATE SET targetT.Taxonomy = sourceT.Taxonomy --Update Only One Column

WHEN    MATCHED AND IsNull(targetT.SPI,'')= '' THEN --Update Rest of the Columns
        UPDATE SET targetT.state_license_no = sourceT.state_license_no, targetT.NPI = sourceT.NPI, targetT.PrefixName = sourceT.PrefixName,targetT.last_name = sourceT.last_name,targetT.first_name = sourceT.first_name
               ,MiddleName = sourceT.MiddleName,targetT.SuffixName = sourceT.SuffixName, targetT.address_1 = sourceT.address_1,targetT.address_2 = sourceT.address_2,targetT.City = sourceT.City,targetT.State = sourceT.State
               ,zip = sourceT.zip,targetT.phone = sourceT.phone,targetT.Fax = sourceT.Fax,targetT.last_modified_date = sourceT.last_modified_date,targetT.Taxonomy = sourceT.Taxonomy           

WHEN    NOT MATCHED BY TARGET --Insert New Row
        THEN
        INSERT (state_license_no, NPI, prefixname, last_name, first_name, MiddleName, SuffixName, address_1, address_2, City, State, zip, phone, Fax, last_modified_date, Taxonomy, Data_source)
                                    VALUES (sourceT.state_license_no, sourceT.NPI, sourceT.PrefixName, sourceT.last_name, sourceT.first_name, sourceT.MiddleName, sourceT.SuffixName, 
                                    sourceT.address_1, sourceT.address_2, sourceT.City, sourceT.State, sourceT.zip, 
                                    sourceT.phone, sourceT.Fax, sourceT.last_modified_date, sourceT.Taxonomy, sourceT.Data_source);

【问题讨论】:

    标签: sql sql-server merge sql-server-2012 sql-update


    【解决方案1】:

    请注意,这并没有回答 OP 问题,它只是对 MERGE 子句的阐述。

    根据MSDN,“如果有两个WHEN MATCHED 子句,则一个必须指定UPDATE 操作,一个必须指定DELETE 操作”。

    WHEN MATCHED THEN <merge_matched>
    

    指定与 ON &lt;merge_search_condition&gt; 返回的行匹配并满足任何其他搜索条件的 target_table 的所有行都根据 子句进行更新或删除。 MERGE 语句最多可以有两个 WHEN MATCHED 子句。

    如果指定了两个子句,则第一个子句必须伴随AND &lt;search_condition&gt; 子句。对于任何给定的行,第二个WHEN MATCHED 子句仅在第一个不适用的情况下才适用。如果有两个 WHEN MATCHED 子句,则一个必须指定 UPDATE 操作,一个必须指定 DELETE 操作。

    如果在 子句中指定了UPDATE,并且超过 的一行与 target_table 中的一行基于 ,SQL Server 返回错误。

    The MERGE statement cannot update the same row more than once, or update and delete the same row.
    

    来源:MSDN

    希望这会有所帮助。

    【讨论】:

    • 这个答案没有帮助。 OP 自己说他知道您发布的内容,并且正在寻求解决问题的方法,而不是重复问题出现的原因。
    • @DRS - 完全同意您的评论。我不记得为什么我在 7 年前回答了这个问题,也许我认为 MSDN 文章对于将来访问这个 SO 页面的人来说是一个很好的阅读。
    【解决方案2】:

    不要将此作为答案,我也没有测试代码。我尝试的是为每一列添加一个 CASE 语句。

    MERGE TargetTable AS targetT 
    USING   SourceTable AS sourceT ON sourceT.Npi = targetT.Npi
    WHEN    MATCHED THEN
            UPDATE  SET targetT.Taxonomy = CASE WHEN  IsNull(targetT.SPI, '') <> '' THEN sourceT.Taxonomy ELSE targetT.Taxonomy END,
                    targetT.state_license_no = CASE WHEN IsNull(targetT.SPI,'')= '' THEN sourceT.state_license_no ELSE targetT.state_license_no END
    WHEN    NOT MATCHED BY TARGET --Insert New Row
            THEN
            INSERT (state_license_no, NPI, prefixname, last_name, first_name, MiddleName, SuffixName, address_1, address_2, City, State, zip, phone, Fax, last_modified_date, Taxonomy, Data_source)
                                        VALUES (sourceT.state_license_no, sourceT.NPI, sourceT.PrefixName, sourceT.last_name, sourceT.first_name, sourceT.MiddleName, sourceT.SuffixName, 
                                        sourceT.address_1, sourceT.address_2, sourceT.City, sourceT.State, sourceT.zip, 
                                        sourceT.phone, sourceT.Fax, sourceT.last_modified_date, sourceT.Taxonomy, sourceT.Data_source);
    

    我只为两列添加了更新。这会很长,但理想情况下必须有效。

    【讨论】:

    • 好主意,但执行起来要花很多时间。
    • 我也会提出同样的建议。这篇文章更详细地讨论了这个想法:blog.jooq.org/2020/04/10/…
    【解决方案3】:

    这是一个巨大的 hack,但您可以定义一个“而不是删除”触发器并将其用于备用更新案例。

    如果在 target_table 上定义了任何 INSTEAD OF UPDATE 或 INSTEAD OF DELETE 触发器,则不会执行更新或删除操作。相反,触发器会触发并相应地填充插入和删除的表

    即您可以执行“匹配时...”(更新)否则(删除)。而不是删除触发器可以进行更新。

    这可能适用于您尝试执行“软删除”的情况

    【讨论】:

      猜你喜欢
      • 2018-03-11
      • 1970-01-01
      • 1970-01-01
      • 2013-06-11
      • 2013-01-26
      • 1970-01-01
      • 1970-01-01
      • 2010-11-28
      • 2016-12-14
      相关资源
      最近更新 更多