PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Verwenden Sie die durch den psql-Metabefehl festgelegte Variable innerhalb des DO-Blocks

Antwort

DO erwartet ein String-Literal mit plpgsql-Code. Symbole werden in Strings in psql nicht ersetzt.
Sie könnten den gesamten String in eine psql-Variable verketten und dann ausführen.

  • Wie werden psql-Variablen verkettet?

Ziemlich mehrzeiliges Format ist nicht möglich, weil (laut Dokumentation):

Aber in jedem Fall können die Argumente eines Meta-Befehls nicht über das Ende der Zeile hinaus fortgesetzt werden.

Einfaches Beispiel:

test=# \set value foo
test=# \set do 'BEGIN\n   RAISE NOTICE ''v: %'', ' :'value' ';\nEND'
test=# DO :'do';
NOTICE:  v: foo

Ersetzen Sie Zeilenumbrüche durch \n (oder entfernen Sie sie, wenn Sie sich nicht für ein hübsches Format interessieren). Basierend auf diesem angepassten 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
'

Es sieht so aus:

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

Ich habe fett hinzugefügt Betonung auf die Variable, damit sie leichter zu erkennen ist.

Zugehörige Antwort von @Pavel (ab)unter Verwendung einer Serversitzungsvariablen:

  • Verweise auf Sitzungsvariablen (\set var='value') von PL/PGSQL

Alternative Lösungen

Vorbereitete Erklärung

Deine jetzige Lösung sieht gar nicht so schlecht aus. Ich würde vereinfachen:

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

Temporäre Tabelle

Ähnliche Lösung mit einer temporären Tabelle:

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