Ric*_*ard 9 postgresql stored-procedures dynamic-sql parameter plpgsql
我想知道这在 Postgres 中是否可行:
最好用一个人为的例子来解释:
create or replace function test_function(filter_param1 varchar default null
, filter_param2 varchar default null)
returns integer as
$$
declare
stmt text;
args varchar[];
wher varchar[];
retid integer;
begin
if filter_param1 is not null then
array_append(args, filter_param1);
array_append(wher, 'parameter_name = $1');
end if;
if filter_param2 is not null then
array_append(args, filter_param2);
array_append(wher, 'parameter_name = $2');
end if;
stmt := 'select id from mytable where ' || array_to_string(wher, ' or ');
execute stmt into retid using args;
return retid;
end;
$$ language plpgsql;
Run Code Online (Sandbox Code Playgroud)
在 Python 中有*args- 也许 PostgreSQL 有类似的机制?
编辑 Erwin Brandstetter 问题:
filter参数都将应用于不同的列,但应该进行 AND 运算。setof在这里更有意义。varchar)。无论哪种方式,这都是完全可能的,因为您的所有参数都具有相同的数据类型。
EXECUTE ... USING愉快地接受一个数组,它被视为单个参数。使用数组下标访问元素。
create or replace function test_function(_filter1 text = null
, _filter2 text = null
, OUT retid int) as
$func$
declare
_args text[] := ARRAY[_filter1, _filter2];
_wher text[];
begin
if _filter1 is not null then
_wher := _wher || 'parameter_name = $1[1]'; -- note array subscript
end if;
if _filter2 is not null then
_wher := _wher || 'parameter_name = $1[2]'; -- assign the result!
end if;
IF _args IS NULL -- check whether all params are NULL
RAISE EXCEPTION 'At least one parameter required!';
END IF;
execute 'select id from mytable where ' -- cover case with all params NULL
|| array_to_string(_wher, ' or ')
|| ' ORDER BY id LIMIT 1'; -- For a single value (???)
into retid
using _args;
end
$func$ language plpgsql;Run Code Online (Sandbox Code Playgroud)
这只是一个概念证明,并且不必要地复杂化。对于实际的数组输入,这将是一个有趣的选项,例如使用 [ VARIADICfunction][2]。例子:
对于手头的情况,请改用:
CREATE OR REPLACE FUNCTION test_function(_filter1 text = null
, _filter2 text = null)
RETURNS SETOF int AS
$func$
DECLARE
_wher text := concat_ws(' OR '
, CASE WHEN _filter1 IS NOT NULL THEN 'parameter_name = $1' END
, CASE WHEN _filter2 IS NOT NULL THEN 'parameter_name = $2' END);
BEGIN
IF _wher = '' -- check whether all params are NULL
RAISE EXCEPTION 'At least one parameter required!';
END IF;
RETURN QUERY EXECUTE 'SELECT id FROM mytable WHERE ' || _wher
USING $1, $2;
-- USING _filter1 , filter2; -- alternatively use func param names
END
$func$ LANGUAGE plpgsql;Run Code Online (Sandbox Code Playgroud)
USING按出现顺序列出子句中动态查询中可能引用的所有值。如果不是所有这些都将在动态查询中被引用,那也没有什么坏处。但是我们需要保持有序位置不变。
特别要注意的是,在动态查询内部,按序数引用子句的给定值,而在子句中引用函数参数。相同的语法,不同的范围!为了简单起见,
在我的示例中引用。但是可以以任何方式对子句中的值重新排序,以便(例如)在动态查询中引用子句中的第二个位置,它引用了第一个函数参数。$n USING$n USING$2$2USING$2$1USING
这允许具有任何(异构)数据类型的任意数量的参数。
在这个例子中返回一组整数(RETURNS SETOF int),它更适合这个例子 - 相应地使用RETURN QUERY EXECUTE。
concat_ws() 有条件地组合 OR 或 AND 谓词列表特别方便。
| 归档时间: |
|
| 查看次数: |
16935 次 |
| 最近记录: |