postgresql 转换表中除某些列之外的所有列

bihw5rsg  于 2022-11-04  发布在  PostgreSQL
关注(0)|答案(1)|浏览(131)

在Postgres中,我取表的每一行,并添加一个新列,该列是该行内容的md5哈希。

alter table my_table add hash_col text;
update my_table set hash_col =md5(cast((my_table.*) as text));

我唯一的问题是如何转换除1或2之外的所有列?现在的转换函数是:

cast(my_table.*)

我想要的结果的伪代码是:

cast(my_table.* EXCEPT col1, col2)
ukdjmx9f

ukdjmx9f1#

“除这些列之外的所有列”

不幸的是,SQL无法表示 “表中除这些列之外的所有列”,它只能表示 “表中的所有列”,并使用SELECT *
您***可以***使用jsonb执行类似的操作:

SELECT to_jsonb(my_table) - '{col1, col2}' FROM my_table;

这是可行的:

UPDATE my_table t
SET    hash_col = md5((to_jsonb(t.*) - '{col1, col2}'::text[])::text);

相关:

  • Select columns inside json_agg
    但是,这要比拼写要包含的列成本高得多。(较长的)文本表示形式。如果您以后更改my_table的表定义,则很可能会破坏现有的哈希值。因此,它通常也比拼写出要包含的列更不安全

正确的解决方案

拼出剩余的列。通过将哈希生成封装在一个函数中,使重复列列表(可能很长?)变得更简单、更安全:

CREATE OR REPLACE FUNCTION public.f_myhash(col3 int, col4 int, col5 text)
  RETURNS uuid
  LANGUAGE sql IMMUTABLE COST 25 PARALLEL SAFE AS 
'SELECT md5(textin(record_out(($1,$2,$3))))::uuid';

根据实际列表调整列名和类型。
然后道:

ALTER TABLE my_table ADD hash_col uuid;
UPDATE my_table SET hash_col = public.f_myhash(col3, col4, col5);

在此过程中,我将MD5哈希转换为uuid类型,该类型在各方面都比uuid类型上级。请参见:

如果你实际上不需要MD5,可以考虑使用hash_record_extended(),它更简单、更快,但是它“只”生成一个bigint哈希。
也许一个表达式索引就足够好了,甚至不需要添加另一列?
请参阅(!):


相关问题