如何为postgres中的所有行生成随机字符串

问题描述 投票:0回答:3

我有

foo
表,想将
bar
列设置为随机字符串。我有以下疑问:

update foo
set bar = select string_agg(substring('0123456789bcdfghjkmnpqrstvwxyz', round(random() * 30)::integer, 1), '')
          from generate_series(1, 9);

但它会生成一次随机字符串并将其重复用于所有行。如何让它为每一行生成一个随机字符串?

我知道我可以让它成为这样的函数:

create function generate_bar() returns text language sql as $$
  select string_agg(substring('0123456789bcdfghjkmnpqrstvwxyz', round(random() * 30)::integer, 1), '')
  from generate_series(1, 9)
$$;

然后调用更新查询中的函数。但我更喜欢在没有函数的情况下完成它。

sql postgresql
3个回答
3
投票

对于包含最多 32 个字符的随机大小写混合数字字符串,请使用:

UPDATE "foo" SET "bar"= substr(md5(random()::text), 0, XXX);

并将 XXX 替换为所需字符串的长度加一。 要替换所有长度为 32 的字符串,示例:

UPDATE "foo" SET "bar"= substr(md5(random()::text), 0, 33);

14235ccd21a408149cfbab0a8db19fb2
可能是填充其中一行的值。每行都有一个随机字符串,但不保证唯一。

用于生成超过 32 个字符的字符串

只需将以上内容与

CONCAT

结合起来即可

2
投票

问题是 Postgres 优化器太聪明了,它决定只能对所有行执行一次子查询。嗯——它确实缺少一些明显的东西——

random()
函数使子查询易失性所以这不是合适的行为。

解决这个问题的一种方法是使用相关子查询。这是一个例子:

update foo
    set bar = array_to_string(array(select string_agg(substring('0123456789bcdfghjkmnpqrstvwxyz', round(random() * 30)::integer, 1), '')
                                    from generate_series(1, 9)
                                    where foo.bar is distinct from 'something'
                                   ), '');

这里是一个db<>小提琴。


0
投票

不如答案,但如果你想生成一个包含几个字母的随机字符串,你也可以使用:

UPDATE foo
    SET bar = CONCAT(
        SUBSTRING('abcdefghijklmnopqrstuvwxyz', round(random() * 30)::integer + 1, 1),
        SUBSTRING('abcdefghijklmnopqrstuvwxyz', round(random() * 30)::integer + 1, 1),
        SUBSTRING('abcdefghijklmnopqrstuvwxyz', round(random() * 30)::integer + 1, 1))
        );
© www.soinside.com 2019 - 2024. All rights reserved.