如何md5所有列,无论类型

时间:2013-01-29 05:06:18

标签: sql postgresql md5 plpgsql

我想创建一个sql查询(或plpgsql),它将md5()所有给定的行,无论类型如何。但是,在下面,如果一个为null,则哈希为空:

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

我稍后使用哈希来比较唯一性,因此空哈希不适用于此用例。

问题在于它处理连接空值的方式。例如:

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

1Type113225  
<NULL>
2Type11751222 
3Type10651010 
4Type10651

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

4 个答案:

答案 0 :(得分:25)

有更优雅的解决方案。

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

有了这个,您可以获得所有列的md5,如下所示:

SELECT md5(mytable::TEXT)
FROM mytable

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

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

关于此解决方案的另一个不错的属性是md5NULL与空字符串的不同。

强制性SQLFiddle

答案 1 :(得分:3)

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

  

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

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

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

这可能会在没有为char添加第二个NVL2函数参数的情况下工作,但如果您尝试从date列获取md5并使用null值,它肯定会失败。 我希望这会对某人有所帮助。

答案 2 :(得分:0)

您是否尝试过使用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

答案 3 :(得分:0)

从financial_cfop中选择MD5(广播(以文本形式显示p))为p