如果在 Merge 中更新时旧值未更改,则不要更新 Merge 语句中的值

问题描述

MERGE PFM_EventPerformance_MetaData AS TARGET
USING
(
    SELECT
         [InheritanceMeterID] = @InheritanceMeterPointID,[SubHourlyScenarioResourceID] = @SubHourlyScenarioResourceID,[MeterID] = @MeterID--internal ID,[BaselineID] = @BaselineID--internal ID,[UpdateUtc] = GETUTCDATE()
) 
AS SOURCE ON
    TARGET.[SubHourlyScenarioResourceID] = SOURCE.[SubHourlyScenarioResourceID]
    AND TARGET.[MeterID] = SOURCE.[MeterID]--internal ID
    AND TARGET.[BaselineID] = SOURCE.[BaselineID]--internal ID
WHEN MATCHED  THEN UPDATE SET
     @MetaDataID = TARGET.ID--get preexisting ID when exists (must populate one row at a time),InheritanceMeterID = SOURCE.InheritanceMeterID,[UpdateUtc] = SOURCE.[UpdateUtc]
WHEN NOT MATCHED
    THEN INSERT
    (
         [InheritanceMeterID],[SubHourlyScenarioResourceID],[MeterID]--internal ID,[BaselineID]--internal ID                          
    )
    VALUES
    (
         SOURCE.[InheritanceMeterID],SOURCE.[SubHourlyScenarioResourceID],SOURCE.[MeterID]--internal ID,SOURCE.[BaselineID]--internal ID                           
    );

在上面的查询中,如果旧值没有变化,我不想更新目标表中的值。我不确定如何实现这一点,因为我很少使用 Merge 语句。请帮我解决。提前致谢

解决方法

最好分两个阶段完成。

第 1 阶段:根据条件合并更新

SO Answer from before(感谢@Laurence!)

第 2 阶段:要比较的哈希键条件

限制:最多 4000 个字符,包括列分隔符

在一个条件下比较多列的一种相当简单的方法是在两侧使用 HASHBYTES(, ) 生成的计算列。

这将编写大量代码从合并语句转移到表生成。

快速示例:

CREATE TABLE dbo.Test
(
  id_column  int   NOT NULL,dsc_name1  varchar(100),dsc_name2  varchar(100),num_age    tinyint,flg_hash   AS HashBytes( 'SHA1',Cast( dsc_name1 AS nvarchar(4000) ) 
      + N'•' + dsc_name2 + N'•' + Cast( num_age AS nvarchar(3) )
      ) PERSISTED
)
;

比较源和目标之间的列 flg_hash 将使比较快速,因为它只是两个 20 位 varbinary 列之间的比较。

HashBytes 一起工作的几个 Caveat Emptor:

  • 函数仅适用于总共 4000 个 nvarchar 字符
  • 短比较代码的权衡在于在视图和表中生成正确的顺序
  • 2^50+ for SHA1 附近有重复的碰撞机会 - 作为安全机制,这现在被认为是不安全的,几年前 MS 试图放弃 SHA1 作为算法
  • 如果哈希字节代码不在修正考虑范围内,则可以从比较中忽略向表和视图添加的列
  • 总的来说,我发现在比较多个列时,这会使我的服务器引擎过载,但从未遇到过哈希键比较问题