使用临时表创建函数,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 BY
的 LIMIT
会产生任意结果。我假设你知道这一点。
如果由于某种原因你确实需要临时 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)
我需要创建一个函数,它是 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 BY
的 LIMIT
会产生任意结果。我假设你知道这一点。
如果由于某种原因你确实需要临时 tables 并且不能升级到 Greenplum 5.0 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)