Antwoord
DO
verwacht een letterlijke tekenreeks met plpgsql-code. Symbolen worden niet vervangen binnen strings in psql.
Je zou de hele string kunnen samenvoegen tot een psql-variabele en vervolgens voer het uit.
- Hoe psql-variabelen samenvoegen?
Mooi meerregelig formaat is niet mogelijk, omdat (volgens documentatie):
Maar in ieder geval kunnen de argumenten van een meta-commando niet verder gaan dan het einde van de regel.
Eenvoudig voorbeeld:
test=# \set value foo
test=# \set do 'BEGIN\n RAISE NOTICE ''v: %'', ' :'value' ';\nEND'
test=# DO :'do';
NOTICE: v: foo
Vervang regeleinden door \n
(of verwijder ze als je niet om mooi formaat geeft). Op basis van deze aangepaste code:
DO
'
DECLARE
_val text;
_vals text[] := string_to_array(>>values<<, '','');
BEGIN
FOREACH _val IN ARRAY _vals
LOOP
RAISE NOTICE ''v: %'', _val;
END LOOP;
END
'
Het ziet er zo uit:
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
Ik heb vet . toegevoegd nadruk op de variabele om deze gemakkelijker te kunnen herkennen.
Gerelateerd antwoord door @Pavel (ab)met behulp van een serversessievariabele:
- Verwijzend naar sessievariabelen (\set var='value') uit PL/PGSQL
Alternatieve oplossingen
Voorbereide verklaring
Je huidige oplossing ziet er niet zo slecht uit. Ik zou vereenvoudigen:
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$;
Tijdelijke tafel
Vergelijkbare oplossing met een tijdelijke tabel:
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$;