Odpowiedź
DO
oczekuje literału z kodem plpgsql. Symbole nie są podstawiane wewnątrz ciągów w psql.
Możesz połączyć cały ciąg w zmienną psql i następnie wykonaj go.
- Jak połączyć zmienne psql?
Dość wielowierszowy format nie jest możliwy, ponieważ (zgodnie z dokumentacją):
Ale w każdym razie argumenty metakomendy nie mogą być kontynuowane poza koniec linii.
Prosty przykład:
test=# \set value foo
test=# \set do 'BEGIN\n RAISE NOTICE ''v: %'', ' :'value' ';\nEND'
test=# DO :'do';
NOTICE: v: foo
Zamień podziały wierszy na \n
(lub usuń je, jeśli nie zależy Ci na ładnym formacie). Na podstawie tego dostosowanego kodu:
DO
'
DECLARE
_val text;
_vals text[] := string_to_array(>>values<<, '','');
BEGIN
FOREACH _val IN ARRAY _vals
LOOP
RAISE NOTICE ''v: %'', _val;
END LOOP;
END
'
Wygląda to tak:
test=# \set do 'DECLARE\n _val text;\n _vals text[] := string_to_array(' :'values' ', '','');\nBEGIN\n FOREACH _val IN ARRAY _vals\n LOOP\n RAISE NOTICE ''v: %'', _val;\n END LOOP;\nEND'
test=# DO :'do';
NOTICE: v: foo
NOTICE: v: bar
NOTICE: v: baz
DO
Dodałem pogrubienie nacisk na zmienną, aby łatwiej ją było dostrzec.
Powiązana odpowiedź @Pavel (ab)używanie zmiennej sesji serwera:
- Odwoływanie się do zmiennych sesji (\set var='value') z PL/PGSQL
Alternatywne rozwiązania
Przygotowane oświadczenie
Twoje obecne rozwiązanie nie wygląda tak źle. Upraszczam:
PREPARE get_values AS SELECT * FROM regexp_split_to_table(:'values', ',');
DO
$do$
DECLARE
_val text;
BEGIN
FOR _val IN EXECUTE
'EXECUTE get_values'
LOOP
RAISE NOTICE 'v: %', _val;
END LOOP;
END
$do$;
Tabela tymczasowa
Podobne rozwiązanie z tabelą tymczasową:
CREATE TEMP TABLE tmp AS SELECT * FROM regexp_split_to_table(:'values', ',') v;
DO
$do$
DECLARE
_val text;
BEGIN
FOR _val IN
TABLE tmp
LOOP
RAISE NOTICE 'v: %', _val;
END LOOP;
END
$do$;