使用 'FOR XML RAW' 避免在调用 'HashBytes' 时出现多行

Avoiding multiple rows in call to 'HashBytes' with 'FOR XML RAW'

在通用 ETL 流程中,我从源(表、文件、网络服务等)中选择数据并将其放入数据集市。

我正在使用 MS-SQL 哈希字节函数来确定某行是否已更改。

例如在带有 CountryCode、Zip 和 CityName 的城市表上,主键 = CountryCode 和 Zip

 SELECT CountryCode, Zip,  CityName, 
 CONVERT(VARCHAR(40), HASHBYTES('MD5', 
 (SELECT CityName FROM spo.City sub 
  WHERE sub.Zip = main.Zip  
    AND  sub.CountryCode = main.CountryCode  
    FOR XML RAW )), 2) AS SysCheckSumSCD1 
FROM spo.City main 

我的问题是源中有重复的主键

然后在 HASHBYTES 中使用的子选择将包括两列,两行将具有相同的哈希键。因此我的数据集市将无法正确更新。 此外,我不会被告知源中有重复项。

示例结果:

Zip     CountryCode     CityName        SysCheckSumSCD1
14600   FR              Honfleur        6D8EF511B35621FC0F5CC67AA6B98EEA
14600   FR              Equemauville    6D8EF511B35621FC0F5CC67AA6B98EEA

相反,我希望调用失败。

之前我使用了 CHECKSUM 函数,该函数将实际行作为输入,但在上面的示例中失败了。 但我不得不更改为 HASHBYTES,不幸的是它只接受一个字符串作为输入。这就是 'FOR XML RAW' 部分

的原因

如果有任何有用的意见,我将不胜感激。 最好仅通过更改上述 SQL 语句即可实现,因为它是大型通用解决方案的一部分。而且我的手有点被束缚了。

我一直在考虑添加一个虚拟聚合函数来强制错误。但是一直没弄明白怎么做。

周末带着充电的大脑回到键盘后。我意识到解决方案其实很简单。

只需在传递给 HASHBYTES 的语句周围添加 'SELECT () AS FOO' 使其成为一个子查询。 :-|

所以声明将如下所示。

SELECT CountryCode, Zip,  CityName, 
CONVERT(VARCHAR(40), HASHBYTES('MD5', 
     (SELECT 
      (SELECT CityName 
      FROM spo.City sub 
      WHERE sub.Zip = main.Zip 
      AND  sub.CountryCode = main.CountryCode) AS FOO 
     FOR XML RAW )), 2) AS SysCheckSumSCD1 
FROM spo.City main