PostgreSQL传播数组值作为using子句的输入参数

时间:2019-10-07 23:10:25

标签: postgresql

CREATE OR REPLACE FUNCTION demo(vsql text, vals text[])
  RETURNS void AS
$BODY$
BEGIN

    execute vsql using vals;

END;
$BODY$
LANGUAGE plpgsql VOLATILE;


select demo('select $1 || $2', ARRAY['Barrett', ' Gilmour'] );

ERROR:  there is no parameter $2
LINE 1: select $1 || $2

错误是postgres无法理解必须将数组中的两项扩展到输入参数$ 1和$ 2。它将整个数组理解为$ 1的值

1 个答案:

答案 0 :(得分:0)

如在问题https://dba.stackexchange.com/questions/83278/postgressql-dynamic-execute-with-argument-values-in-array中所讨论的,EXECUTE ... USING将把数组视为单个参数。

您可以尝试使用此技巧,该技巧可以编辑传递的SQL语句,使$ n变为$ 1 [n]

vsql := regexp_replace( vsql, '[$]([0-9]+)', '$1[\1]', 'g' );

将数组vals视为单个参数,但是参数化的select可以将其索引以获取元素。

a_horse_with_no_name提到了另一个问题,即您的函数实际上未返回任何内容。如果要查看正在执行什么:

-- anyelement is a polymorphic pseudo-type
-- problem with returning 'setof record' is that select * from so_demov3() gives error 
--  ERROR: a column definition list is required for functions returning "record"

drop function so_demov3(anyelement, text, text[]);
create function so_demov3(rec_type anyelement, p_sql text, p_vals text[]) returns setof anyelement  as
$$
declare v_sql text;

begin
  -- edit the executable SQL stmt so that $n -> $1[n]
  v_sql := regexp_replace( p_sql, '[$]([0-9]+)', '$1[\1]', 'g' );
  return query execute v_sql using p_vals;
end;
$$
language plpgsql volatile;

并这样称呼它:

select * from so_demov3(null::text, 'select $1 || $2', array['Barrett', 'Gilmour'] );