如何在 PostgreSQL 中执行动态查询?

jli*_*ted 1 postgresql dynamic-sql postgresql-9.3

我正在尝试执行以下动态 sql,但我不知道该怎么做:

DROP FUNCTION f_mycross(text, text);

EXECUTE ('CREATE OR REPLACE FUNCTION f_mycross(text, text)
   RETURNS TABLE ("registration_id" integer, '
   || (SELECT string_agg(DISTINCT pivot_headers, ',' order by pivot_headers)
       FROM (SELECT DISTINCT '"' || qid::text || '" text' AS pivot_headers
             FROM answers) x)
   || ') AS ''$libdir/tablefunc'',''crosstab_hash'' LANGUAGE C STABLE STRICT;')
Run Code Online (Sandbox Code Playgroud)

我对 PostgreSQL 比较陌生。

Erw*_*ter 5

EXECUTE不是 SQL 命令。它是一个 PL/pgSQL 命令,只能在该过程语言的代码块中使用。喜欢:

DROP FUNCTION IF EXISTS f_mycross(text, text);

DO
$do$
BEGIN
   EXECUTE (
   SELECT 'CREATE OR REPLACE FUNCTION f_mycross(text, text)
             RETURNS TABLE (registration_id integer, '
       || string_agg(pivot_header || ' text', ', ')
       || $c$) AS '$libdir/tablefunc', 'crosstab_hash' LANGUAGE C STABLE STRICT$c$
   FROM  (SELECT DISTINCT quote_ident(qid::text) AS pivot_header FROM answers ORDER BY 1) x
   );
END
$do$;  -- LANGUAGE plpgsql is the default
Run Code Online (Sandbox Code Playgroud)

我添加了一些改进并简化了嵌套SELECT查询。

主要观点

  • 添加IF EXISTSDROP FUNCTION除非您确定该函数存在或者您希望在不存在时引发异常。

  • DISTINCT在子查询中就足够了,不需要DISTINCT在外部中另一个SELECT

  • 用于在必要时自动使用quote_ident()双引号标识符。否则,您可能会遇到语法错误和 SQL 注入。

  • 我们提供给 的字符串不需要括号EXECUTE

  • 使用美元引号进行更简单的嵌套引用:

  • 我们可以在子查询中应用,这通常比在外部聚合函数中ORDER BY添加要快得多。ORDER BY