无论类型如何,如何对所有列进行md5处理

问题描述 投票:7回答:4

我想创建一个sql查询(或plpgsql),该查询将对所有给定的行进行md5(),而与类型无关。但是,在下面,如果一个为空,则哈希为空:

UPDATE thetable 
    SET hash = md5(accountid || accounttype || createdby || editedby);

我稍后将使用散列比较唯一性,因此空散列不适用于此用例。

问题是它处理串联null的方式。例如:

thedatabase=# SELECT accountid || accounttype || createdby  || editedby 
                 FROM thetable LIMIT 5;  

1Type113225  
<NULL>
2Type11751222 
3Type10651010 
4Type10651

如果知道类型,则可以使用合并或CASE语句;但是,我有很多表,而且我不会提前知道每一列的类型。

sql postgresql md5 plpgsql
4个回答
31
投票

对此有更优雅的解决方案。

在Postgres中,允许在SELECT中使用表名,并且其类型为ROW。如果将其强制转换为TEXT类型,则它会将所有列串联在一起,而该字符串实际上是JSON。

有了这个,您可以按以下方式获得所有列的md5

SELECT md5(mytable::TEXT)
FROM mytable

如果只想使用某些列,请使用ROW构造函数并将其强制转换为TEXT

SELECT md5(ROW(col1, col2, col3)::TEXT)
FROM mytable

关于此解决方案的另一个不错的特性是md5与空字符串相比NULL会有所不同。

必填SQLFiddle


5
投票

您还可以使用类似于mvp解决方案的其他方式。而不是使用Amazon Redshift不支持的ROW()函数...

无效操作:目标列表中不支持ROW表达式,无论是隐式还是显式;

我的主张是使用NVL2和CAST函数将不同类型的列转换为CHAR,只要该类型与根据documentation的所有Redshift数据类型兼容即可。下面是一个如何在Redshift中实现nullproof MD5的示例。

SELECT md5(NVL2(col1,col1::char,''), 
           NVL2(col2,col2::char,''), 
           NVL2(col3,col3::char,''))
FROM mytable

这可能在不将第二个NVL2函数参数强制转换为char的情况下起作用,但是如果您尝试从具有空值的date列中获取md5,则肯定会失败。我希望这会对某人有所帮助。


2
投票

您是否尝试过使用CONCAT()?我只是在PG 9.1安装中尝试过:

SELECT CONCAT('aaaa',1111,'bbbb');     => aaaa1111bbbb
SELECT CONCAT('aaaa',null,'bbbb');     => aaaabbbb

因此,您可以尝试:

SELECT MD5(CONCAT(column1, column2, column3, column_n))    => md5_hash string here

0
投票

从fiscal_cfop中选择MD5(以文本形式广播(以文本形式广播))>

© www.soinside.com 2019 - 2024. All rights reserved.