I have foo
table and would like to set bar
column to a random string. I've got the following query:
update foo
set bar = select string_agg(substring('0123456789bcdfghjkmnpqrstvwxyz', round(random() * 30)::integer, 1), '')
from generate_series(1, 9);
But it generates the random string once and reuse it for all rows. How can I make it to generate one random string for each row?
I know I can make it a function like this:
create function generate_bar() returns text language sql as $$
select string_agg(substring('0123456789bcdfghjkmnpqrstvwxyz', round(random() * 30)::integer, 1), '')
from generate_series(1, 9)
$$;
and then call the function in the update query. But I'd prefer to do it without a function.
The problem is that the Postgres optimizer is just too smart and deciding that it can execute the subquery only once for all rows. Well -- it is really missing something obvious -- the random()
function makes the subquery volatile so this is not appropriate behavior.
One way to get around this is to use a correlated subquery. Here is an example:
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'
), '');
Here is a db<>fiddle.