我想知道如何在函数内使用动态查询。我尝试了很多方法,但是,当我尝试编译我的函数时,会显示一条消息 SQL 42601。
我使用的代码:
CREATE OR REPLACE FUNCTION prc_tst_bulk(sql text)
RETURNS TABLE (name text, rowcount integer) AS
$$
BEGIN
WITH v_tb_person AS (return query execute sql)
select name, count(*) from v_tb_person where nome like '%a%' group by name
union
select name, count(*) from v_tb_person where gender = 1 group by name;
END
$$ LANGUAGE plpgsql;
我收到的错误消息:
ERROR: syntax error at or near "return"
LINE 5: WITH v_tb_person AS (return query execute sql)
我尝试使用:
WITH v_tb_person AS (execute sql)
WITH v_tb_person AS (query execute)
WITH v_tb_person AS (return query execute)
出了什么问题?我该如何解决这个问题?
你的函数将像这样工作:
CREATE OR REPLACE FUNCTION prc_tst_bulk(sql text)
RETURNS TABLE (name text, rowcount int)
LANGUAGE plpgsql AS
$func$
BEGIN
RETURN QUERY EXECUTE '
WITH v_tb_person AS (' || sql || $x$)
SELECT name, count(*)::int FROM v_tb_person WHERE nome LIKE '%a%' GROUP BY name
UNION
SELECT name, count(*)::int FROM v_tb_person WHERE gender = 1 GROUP BY name$x$;
END
$func$;
致电:
SELECT * FROM prc_tst_bulk($$SELECT a AS name, b AS nome, c AS gender FROM tbl$$)
您无法按照您尝试的方式混合普通 SQL 和动态 SQL。整个语句要么都是动态的,要么都是纯 SQL 的。因此,我正在构建一个动态声明来使这项工作发挥作用。您可能对手册中关于执行动态命令的章节感兴趣。
聚合函数
count()
返回 bigint
,但您已将 rowcount
定义为 integer
,因此您需要显式转换 ::int
才能完成这项工作。
我使用美元引用来避免引用地狱。
但是,这应该是用于SQL注入攻击的蜜罐还是你真的要使用它?对于您非常私密和安全的使用,这可能还不错 - 尽管我什至不相信自己有这样的功能。如果不受信任的用户有任何可能的访问权限,那么这样的功能就是一把上膛的枪。不可能保证这个安全。
Craig(SQL 注入的死敌)看到您根据“他对前面问题的回答”伪造的内容时,可能会受到轻微的打击。 :) 顺便说一句,查询本身看起来相当奇怪。这两个
SELECT
项可能会合并为一个。但这不是重点。