10

是否有一种“半便携式”方式来获取整行的 md5() 或 sha1()?(或者更好的是,按所有字段排序的一整组行,即order by 1,2,3,...,n)?不幸的是,并不是所有的数据库都是 PostgreSQL……我至少要处理微软 SQL 服务器、Sybase 和 Oracle。

理想情况下,我希望有一个聚合器(服务器端)并使用它来检测行组中的更改。例如,在有一些时间戳列的表中,我想为每个月存储一个唯一的签名。然后我可以快速检测到自上次访问以来发生变化的月份(我将某些表镜像到运行 Greenplum 的服务器)并重新加载这些表。

我查看了一些选项,例如checksum(*)在 tsql 中(恐怖:它很容易发生冲突,因为它基于一堆 XOR 和 32 位值),hashbytes('MD5', field)但是后者不能应用于整行. 这将为我提供一个解决方案,只针对我必须处理的一种 SQL 风格。

任何想法?即使只是上面提到的一种 SQL 习惯用法,那也很棒。

4

2 回答 2

8

您可以在更新触发器上计算整行的 hashbytes 值,我将其用作 ETL 过程的一部分,以前他们比较表中的所有列,速度提高很大。

Hashbytes 适用于 varchar、nvarchar 或 varbinary 数据类型,我想比较整数键和文本字段,转换所有内容将是一场噩梦,因此我在 SQL Server 中使用 FOR XML 子句,如下所示:

CREATE TRIGGER get_hash_value ON staging_table
FOR UPDATE, INSERT AS  
UPDATE staging_table
SET sha1_hash = (SELECT hashbytes('sha1', (SELECT col1, col2, col3 FOR XML RAW)))
GO

或者,如果您计划通过使用带有 for xml 子句的子查询对所有行进行多次更新,则可以在触发器之外以类似的方式计算值。如果走这条路,您甚至可以将其更改为 SELECT *,但不能在触发器中更改,因为每次运行它时,您都会得到不同的值,因为 sha1_hash 列每次都会不同。

您可以修改 select 语句以获得超过 1 行

于 2013-05-22T18:44:57.683 回答
5

在 MSSQL 中——您可以通过使用 xml.. 在整个行中使用 HashBytes。

SELECT MBT.id,
   hashbytes('MD5',
               (SELECT MBT.*
                FROM (
                      VALUES(NULL))foo(bar)
                FOR xml auto)) AS [Hash]
FROM <Table> AS MBT;

您需要该from (values(null))foo(bar)子句才能使用 xml auto,它没有其他用途..

于 2016-06-23T05:35:33.433 回答