使用临时表创建函数,该表使用这些临时表返回选择查询

时间:2017-09-24 11:21:12

标签: plpgsql stored-functions greenplum

我需要创建一个函数,它返回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 Database 4.3.12.0 build 1)

2 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:1)

Postgres可能引发的最可能的错误:

  

错误:列“foo”指定了多次

意思是,两个表中至少还有一个列名称(除id之外,它被折叠到一个带有USING子句的实例)。这不会在容错重复输出列名的普通SQL SELECT中引发异常。但是您无法创建具有重复名称的表。

问题也适用于 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;

该示例不需要临时表 - 除非您在同一事务(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

除此之外:LIMIT没有ORDER BY会产生任意结果。我假设你知道这一点。

如果由于某种原因你真的需要临时表并且无法升级到Greenplum 5.0 like A. Scherbaum suggested,你仍然可以在Greenplum 4.3.x中使用它(就像在Postgres 8.2中一样)。将 FOR 循环与 RETURN NEXT 结合使用。
例子: