В сообщении блога Брюса Момджяна Генерация случайных данных с помощью SQL он использовал следующий код для генерации 5 случайных строк:
SELECT
(
SELECT string_agg(x, '')
FROM (
SELECT chr(ascii('a') + floor(random() * 26)::integer)
FROM generate_series(1, 40 + b * 0) as f(g)
) AS y(x)
) AS result
FROM generate_series(1,5) as a(b);
result
------------------------------------------
plwfwcgajxdygfissmxqsywcwiqptytjjppgrvgb
sjaypirhuoynnvqjdgywfsfphuvzqbbilbhakyhf
ngtabkjfqibwahlicgisijatliuwgbcuiwujgeox
mqtnyewalettounachwjjzdrvxbbbpzogscexyfi
dzcstpsvwpefohwkfxmhnlwteyybxejbdltwamsx
(5 rows)
Я задавался вопросом, почему требуется «b *0» в строке 6. Когда я удалил его, результат изменился на 5 точно похожих строк, что означает, что Postgres кэшировал выражение внешнего выбора (result )!
Я не смог найти, как кэширование выражений работает в Postgres. В соответствии с документация random ()функция помечена как VOLATILE, поэтому я ожидаю, что любое выражение зависит от нее, также будет изменчивым.
Как работает кэширование выражений в Postgres? Это где-нибудь задокументировано? Почему «b *0» отключил кеш, а random ()нет?
Обновление:
Чтобы изучить проблему, я переместил «b *0» внутрь вызова пола (), чтобы он находился на той же позиции / уровне, что и случайный ():
...
SELECT chr(ascii('a') + floor(random() * 26 + b * 0)::integer)
FROM generate_series(1, 40) as s(f)
...
. Результат все еще не кэшируется; разные струны.
Обновление :Еще один пример, показывающий проблему
create sequence seq_test;
SELECT (SELECT nextval('seq_test')) FROM generate_series(1,5);
?column?
----------
1
1
1
1
1
(5 rows)