【问题标题】:PostgreSQL - SQL state: 42601 syntax errorPostgreSQL - SQL 状态:42601 语法错误
【发布时间】:2013-04-23 21:42:02
【问题描述】:

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

【问题讨论】:

  • 这显然是 plpgsql 语法。 [Oracle] 标签在这里做什么?
  • @ErwinBrandstetter 上一个问题是关于将 PL/SQL 转换为 PL/PgSQL,所以可能会继续。我已经删除了标签。
  • 文档是值得一试的。大量精力投入到 PostgreSQL(和 PL/PgSQL)文档中。在这种情况下,您需要以 Dynamic statements in PL/PgSQL 开头。

标签: database postgresql plpgsql bulkinsert dynamic-sql


【解决方案1】:

你的函数会这样工作:

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。整个语句要么全是动态的,要么全是纯 SQL。因此,我正在构建一个动态声明来完成这项工作。你可能对executing dynamic commands in the manual的章节感兴趣。

  • 聚合函数 count() 返回 bigint,但您将 rowcount 定义为 integer,因此您需要显式转换 ::int 才能完成这项工作

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

然而,这应该是SQL injection 攻击的蜜罐,还是您真的要使用它?对于您非常私密和安全的使用,它可能没问题 - 尽管我什至不相信自己拥有这样的功能。如果不受信任的用户有任何可能的访问权限,那么这样的功能就是一个加载的脚枪。这是不可能的 确保安全。

Craig(SQL 注入的死敌!)当他看到你在your preceding question 的答案中从他的代码中伪造的内容时,可能会受到轻击。 :)

查询本身似乎很奇怪,顺便说一句。但这不是重点。

【讨论】:

  • 我实际上认为这种事情比接受未经检查的参数更少糟糕。如果您接受整个原始 SQL 语句,则您已经知道您的输入必须来自完全受信任的来源或具有与该函数执行的相同 priv 级别的来源。现在,如果它的功能也是SECURITY DEFINER...
  • @CraigRinger:总而言之,我希望我的话没有完全错误地引用你的话。在这种情况下,我应该删除它。
  • 不,一切都很好。我向你保证,它仍然让我抽搐。
猜你喜欢
  • 2021-02-28
  • 1970-01-01
  • 1970-01-01
  • 2016-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-11
相关资源
最近更新 更多