如何md5所有列,无论类型

bri*_*ray 7 sql postgresql md5 plpgsql

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

UPDATE thetable 
    SET hash = md5(accountid || accounttype || createdby || editedby);
Run Code Online (Sandbox Code Playgroud)

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

问题是它处理连接空值的方式.例如:

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

1Type113225  
<NULL>
2Type11751222 
3Type10651010 
4Type10651
Run Code Online (Sandbox Code Playgroud)

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

mvp*_*mvp 29

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

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

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

SELECT md5(mytable::TEXT)
FROM mytable
Run Code Online (Sandbox Code Playgroud)

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

SELECT md5(ROW(col1, col2, col3)::TEXT)
FROM mytable
Run Code Online (Sandbox Code Playgroud)

关于这个解决方案的另一个不错的特性是对于空字符串md5将是不同的NULL.

强制性的SQLFiddle.

  • 只为下一个人 - 不,这不适用于redshift.redshift不支持语法(`#SELECT md5(precipitation :: TEXT)来自降水; ERROR:列"降水"不存在于降水中) (3认同)
  • 请使用语法“md5(mytable.*::TEXT)”(注意“.*”)。否则,如果您的表有一个名为“mytable”的列,则摘要将仅由该列组成。 (2认同)

小智 5

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

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

我的提议是使用 NVL2 和 CAST 函数将不同类型的列转换为 CHAR,只要根据文档,这种类型与所有 Redshift 数据类型兼容。下面是如何在 Redshift 中实现空证明MD5的示例。

SELECT md5(NVL2(col1,col1::char,''), 
           NVL2(col2,col2::char,''), 
           NVL2(col3,col3::char,''))
FROM mytable
Run Code Online (Sandbox Code Playgroud)

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