PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Use a variável definida pelo meta-comando do psql dentro do bloco DO

Resposta


DO espera um string literal com código plpgsql. Símbolos não são substituídos dentro de strings no psql.
Você pode concatenar a string inteira em uma variável psql e então execute.
  • Como concatenar variáveis ​​do psql?

O formato bonito de várias linhas não é possível, porque (por documentação):

Mas, de qualquer forma, os argumentos de um metacomando não podem continuar além do fim da linha.

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

Substitua as quebras de linha por \n (ou remova-os se você não se importa com o formato bonito). Com base neste código adaptado:
DO
'
DECLARE
   _val  text;
   _vals text[] := string_to_array(>>values<<, '','');
BEGIN
   FOREACH _val IN ARRAY _vals
   LOOP
     RAISE NOTICE ''v: %'', _val;
   END LOOP;
END
'

Se parece com isso:
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

Eu adicionei negrito ênfase na variável para torná-la mais fácil de identificar.

Resposta relacionada por @Pavel (ab) usando uma variável de sessão do servidor:
  • Referindo-se a variáveis ​​de sessão (\set var='value') de PL/PGSQL

Soluções alternativas

Declaração preparada


Sua solução atual não parece tão ruim. Eu simplificaria:
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$;

Tabela temporária


Solução semelhante com uma tabela temporária:
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$;