这可能在 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 年被添加到 PL/pgSQL 的 8.3 版中,在 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 结合使用。
例子: