簡體   English   中英

在 DO 塊內使用由 psql 元命令設置的變量

[英]Use variable set by psql meta-command inside of DO block

這是我想做的事情:

\set values foo,bar,baz

DO $$
DECLARE
    value  TEXT;
    values TEXT[] := string_to_array(:'values', ',');
BEGIN
    FOREACH value IN ARRAY values LOOP
        raise notice 'v: %', value;
    END LOOP;
END $$ LANGUAGE plpgsql;

這會導致以下錯誤:

 ERROR: syntax error at or near ":" SELECT string_to_array(:'values', ',') INTO values... ^

這是我目前的解決方案,但感覺很hacky:

\set values foo,bar,baz

PREPARE get_values AS SELECT string_to_array(:'values', ',');

DO $$
DECLARE
    value  TEXT;
    values TEXT[];
BEGIN
    EXECUTE 'EXECUTE get_values' INTO values;

    FOREACH value IN ARRAY values LOOP
        raise notice 'v: %', value;
    END LOOP;
END $$ LANGUAGE plpgsql;

回答

DO期望帶有plpgsql代碼的字符串文字 psql中的字符串內部不替換符號。
您可以將整個字符串連接到psql變量, 然后執行它。

漂亮的多行格式是不可能的,因為( 每個文檔 ):

但無論如何,元命令的參數不能超越行尾。

簡單的例子:

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

\\n替換換行符(如果你不關心漂亮的格式,則刪除換行符)。 基於這個改編的代碼:

DO
'
DECLARE
   _val  text;
   _vals text[] := string_to_array(>>values<<, '','');
BEGIN
   FOREACH _val IN ARRAY _vals
   LOOP
     RAISE NOTICE ''v: %'', _val;
   END LOOP;
END
'

它看起來像這樣:

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

大膽強調變量,以便更容易發現。

@Pavel(ab)使用服務器會話變量的相關答案:

替代方案

准備好的聲明

您當前的解決方案看起來並不那么糟糕。 我會簡化:

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

臨時表

使用臨時表的類似解決方案:

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

能夠利用這個解決方案:

我在那里設置變量並使用current_setting()檢索它

\set values foo,bar,baz
SET vars.values TO :'values';

DO $$
DECLARE
    value  TEXT;
    values TEXT[] := string_to_array(current_setting('vars.values'), ',');
BEGIN
    FOREACH value IN ARRAY values LOOP
        RAISE NOTICE 'v: %', value;
    END LOOP;
END $$ LANGUAGE plpgsql

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM