sql >> Database >  >> RDS >> PostgreSQL

Gebruik variabele ingesteld door psql meta-commando in DO-blok

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


  1. MariaDB GROUP_CONCAT()

  2. 3 manieren om de Modulo terug te sturen in MariaDB

  3. Databasekeuze voor het maken van twee gekoppelde tabellen?

  4. Oracle/SQL:waarom vraagt ​​​​query SELECT * FROM records WHERE rownum>=5 AND rownum <=10 - retourneert nul rijen