PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Utiliser la variable définie par la méta-commande psql à l'intérieur du bloc DO

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$;