2013-04-30 1209 views
1

我想知道如何在函数中使用动态查询。我尝试了很多方法,但是,当我尝试编译我的函数时,会显示一条消息SQL 42601。PostgreSQL - 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) 

有什么不对?我怎么解决这个问题?

其有关PostgreSQL equivalent of Oracle “bulk collect”

+0

这显然是plpgsql语法。什么是'[Oracle]'标签在这里做什么? – 2013-04-30 05:29:44

+0

@ErwinBrandstetter上一个问题是关于将PL/SQL转换为PL/PgSQL的问题,所以可能会将其转换。我已经移除了标签。 – 2013-04-30 05:31:27

+0

有一点值得一试,值得一试的是文档。 PostgreSQL(和PL/PgSQL)文档中付出了很多努力。在这种情况下,您需要从[PL/PgSQL中的动态语句]开始(http://www.postgresql.org/docs/current/static/plpgsql-statements.html#PLPGSQL-STATEMENTS-EXECUTING-DYN) 。 – 2013-04-30 05:42:23

回答

2

你的功能的问题就是这样工作的:

CREATE OR REPLACE FUNCTION prc_tst_bulk(sql text) 
RETURNS TABLE (name text, rowcount integer) AS 
$$ 
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  
$$ LANGUAGE plpgsql; 

电话:

SELECT * FROM prc_tst_bulk($$SELECT a AS name, b AS nome, c AS gender FROM tbl$$) 
  • 不能混合平原和动态SQL的方式,你试图去做。整个语句要么全是动态的,要么全是纯SQL。所以我正在建立一个动态声明来完成这项工作。您可能会对关于executing dynamic commands in the manual的章节感兴趣。

  • 聚合函数count()返回bigint,但你已经rowcount定义为integer,所以你需要显式类型转换::int,使这项工作

  • 我用dollar quoting避免引用地狱。

但是,则这应该是一个蜜罐的SQL injection攻击或者你认真地去使用它呢?为了你非常私密和安全的使用,它可能是好的 - 虽然我甚至不相信自己有这样的功能。如果有任何可能的访问不受信任的用户,这样的功能是一个加载的脚枪。 不可能使这个安全。

克雷格(SQL注入的死敌!)可能会轻微的中风,当他看到你在your preceding question的答案中从他的代码段中伪造了什么。 :)

查询本身似乎很奇怪,顺便说一句。但这没有关系。

+0

我其实认为这种事情比接受未经检查的参数要少*差。如果您接受完整的原始SQL语句,则您已知道您的输入必须来自完全可信的源或具有相同特权级别的源,该函数正在执行。现在,如果它的功能也是'SECURITY DEFINER' ... – 2013-04-30 05:34:18

+0

@CraigRinger:总而言之,我希望我的评论没有完全误导你。在这种情况下,我应该删除它。 – 2013-04-30 05:38:05

+1

不错,一切都很好。它仍然给我我向你保证的抽搐。 – 2013-04-30 05:41:03