Ale*_*tin 6 postgresql session-variables dynamic-sql psql postgresql-9.4
这是我想做的事情:
\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;
Run Code Online (Sandbox Code Playgroud)
这导致以下错误:
Run Code Online (Sandbox Code Playgroud)ERROR: syntax error at or near ":" SELECT string_to_array(:'values', ',') INTO values... ^
这是我目前的解决方案,但感觉很糟糕:
\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;
Run Code Online (Sandbox Code Playgroud)
DO需要带有 PL/pgSQL 代码的字符串文字(除非您声明不同的 PL)。psql 中的字符串内部不会替换符号。
您可以将整个字符串连接到 psql 变量中,然后执行它。
漂亮的多行格式是不可能的,因为(根据文档):
但无论如何,元命令的参数不能超出行尾。
简单的例子:
test=# \set value foo
test=# \set do 'BEGIN\n RAISE NOTICE ''v: %'', ' :'value' ';\nEND'
test=# DO :'do';
NOTICE: v: foo
Run Code Online (Sandbox Code Playgroud)
将换行符替换为\n(如果您不喜欢漂亮的格式,则将其删除)。基于此改编代码:
test=# \set value foo
test=# \set do 'BEGIN\n RAISE NOTICE ''v: %'', ' :'value' ';\nEND'
test=# DO :'do';
NOTICE: v: foo
Run Code Online (Sandbox Code Playgroud)
它看起来像这样:
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
DORun Code Online (Sandbox Code Playgroud)
我对变量加了粗体强调,以便更容易发现。
@Pavel (ab)使用服务器会话变量的相关答案:
您当前的解决方案看起来并没有那么糟糕。我会简化:
DO
'
DECLARE
_val text;
_vals text[] := string_to_array(>>values<<, '','');
BEGIN
FOREACH _val IN ARRAY _vals
LOOP
RAISE NOTICE ''v: %'', _val;
END LOOP;
END
'
Run Code Online (Sandbox Code Playgroud)
使用临时表的类似解决方案:
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
DORun Code Online (Sandbox Code Playgroud)