使用临时表创建函数,return 使用这些临时表进行 select 查询

Create function with temporary tables that return a select query using these temp tables

我需要创建一个函数,它是 returns 个 SELECT 查询的结果。此 SELECT 查询是在此函数内创建的几个临时表的 JOIN。有没有办法创建这样的功能?这是一个示例(非常简单,实际上有多个临时表和长查询):

CREATE OR REPLACE FUNCTION myfunction () RETURNS TABLE (column_a TEXT, column_b TEXT) AS $$
BEGIN
CREATE TEMPORARY TABLE raw_data ON COMMIT DROP
AS
SELECT d.column_a, d2.column_b FROM dummy_data d JOIN dummy_data_2 d2 using (id);

RETURN QUERY (select distinct column_a, column_b from raw_data limit 100);
END;
$$
LANGUAGE 'plpgsql' SECURITY DEFINER

我收到错误:

[Error] Script lines: 1-19 -------------------------
 ERROR: RETURN cannot have a parameter in function returning set;
 use RETURN NEXT at or near "QUERY"Position: 237

对于任何明显的错误,我提前道歉,我是新手。

Psql 版本是 PostgreSQL 8.2.15(Greenplum 数据库 4.3.12.0 build 1)

在 Postgres 中最可能出现的错误:

ERROR: column "foo" specified more than once

意思是,在两个table中至少多了一个列名(除了id,它被USING子句折叠成一个实例)。这不会在允许重复输出列名称的普通 SQL SELECT 中引发异常。但是您不能创建具有重复名称的 table。

这个问题也适用于Greenplum(就像你后来声明的那样),即不是 Postgres。它于 2005 年从 PostgreSQL 中分叉出来并单独开发。当前的 Postgres 手册几乎不再适用。查看 Greenplum documentation.

psql只是标准的PostgreSQL交互式终端程序。显然,您使用的是 PostgreSQL 8.2.15 附带的那个,但 RDBMS 仍然是 Greenplum,而不是 Postgres。

语法修复(对于 Postgres,就像您第一次标记一样,仍然相关):

CREATE OR REPLACE FUNCTION myfunction()
  RETURNS TABLE (column_a text, column_b text) AS
$func$
BEGIN
   CREATE TEMPORARY TABLE raw_data ON COMMIT DROP AS
   SELECT d.column_a, d2.column_b  -- explicit SELECT list avoids duplicate column names
   FROM   dummy_data   d
   JOIN   dummy_data_2 d2 using (id);

   RETURN QUERY
   SELECT DISTINCT column_a, column_b
   FROM   raw_data
   LIMIT  100;
END
$func$  LANGUAGE plpgsql SECURITY DEFINER;

该示例不需要临时文件 table - 除非您在同一事务中调用函数后访问临时文件 table (ON COMMIT DROP)。否则,普通的 SQL 函数在各个方面都更好。 Postgres Greenplum 的语法:

CREATE OR REPLACE FUNCTION myfunction(OUT column_a text, OUT column_b text)
  RETURNS SETOF record AS
$func$
   SELECT DISTINCT d.column_a, d2.column_b
   FROM   dummy_data   d
   JOIN   dummy_data_2 d2 using (id)
   LIMIT  100;
$func$  LANGUAGE plpgsql SECURITY DEFINER;

尤其是,it should also work for Greenplum

此功能的唯一剩余原因是 SECURITY DEFINER。否则你可以只使用简单的 SQL 语句(可能是准备好的语句)。

RETURN QUERY 在 2008 年的 8.3 版本中被添加到 PL/pgSQL, Greenplum 的分支之后的几年。可能会解释您的错误信息:

ERROR: RETURN cannot have a parameter in function returning set;
use RETURN NEXT at or near "QUERY" Position: 237

旁白:没有 ORDER BYLIMIT 会产生任意结果。我假设你知道这一点。


如果由于某种原因你确实需要临时 tables 并且不能升级到 Greenplum 5.0 ,你仍然可以让它在 Greenplum 4 中工作。3.x(就像在 Postgres 中一样8.2).将 FOR 循环与 RETURN NEXT.
结合使用 示例:

  • plpgsql error "RETURN NEXT cannot have a parameter in function with OUT parameters" in table-returning function
  • How to use `RETURN NEXT`in PL/pgSQL correctly?

最新版本的Greenplum数据库(5.0)基于PostgreSQL 8.3,支持RETURN QUERY语法。刚刚测试了您的功能:

PostgreSQL 8.4devel (Greenplum Database 5.0.0-beta.10+dev.726.gd4a707c762 build dev)