Répondre
DO
attend un littéral de chaîne avec le code plpgsql. Les symboles ne sont pas substitués à l'intérieur des chaînes dans psql.
Vous pouvez concaténer la chaîne entière dans une variable psql et ensuite exécutez-le.
- Comment concaténer des variables psql ?
Le format assez multiligne n'est pas possible, car (selon la documentation):
Mais dans tous les cas, les arguments d'une méta-commande ne peuvent pas continuer au-delà de la fin de la ligne.
Exemple simple :
test=# \set value foo
test=# \set do 'BEGIN\n RAISE NOTICE ''v: %'', ' :'value' ';\nEND'
test=# DO :'do';
NOTICE: v: foo
Remplacer les sauts de ligne par \n
(ou supprimez-les si vous n'aimez pas le joli format). Basé sur ce code adapté :
DO
'
DECLARE
_val text;
_vals text[] := string_to_array(>>values<<, '','');
BEGIN
FOREACH _val IN ARRAY _vals
LOOP
RAISE NOTICE ''v: %'', _val;
END LOOP;
END
'
Il ressemble à ceci :
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
J'ai ajouté gras mettre l'accent sur la variable pour la rendre plus facile à repérer.
Réponse connexe de @Pavel (ab) en utilisant une variable de session serveur :
- Se référer aux variables de session (\set var='value') de PL/PGSQL
Solutions alternatives
Déclaration préparée
Votre solution actuelle n'a pas l'air si mal. Je simplifierais :
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$;
Tableau temporaire
Solution similaire avec une table temporaire :
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$;