2

在用户定义的函数中,如何返回由连接其他表的投影形成的表?

这是一个简单的例子

CREATE FUNCTION something123(character varying(100)) RETURNS TABLE (a integer, b character varying(300)) AS
$$
  SELECT b.year, p.materialUsed FROM bestBefore b join packaged p on b.id=p.id WHERE id=$1;
$$
LANGUAGE SQL
;

它总是在 TABLE 处出错。您将如何让该 select 语句的内容返回?

我正在使用 Postgres 8.1.21

4

1 回答 1

4

您的代码很好,但您的 PostgreSQL 版本不是。RETURNS TABLE根据PostgreSQL 8.1 文档,CREATE FUNCTION它不支持.

在非常旧的 PostgreSQL 版本(如 8.1)上,您必须RETURNS SETOF RECORD在不使用 using的情况下声明RETURNS TABLE,因为旧版本不支持它。RETURNS SETOF RECORD使函数返回一个匿名记录集。然后,您必须在调用站点指定记录结构,如下所示:

regress=# CREATE FUNCTION something123_legacy(character varying(100))
RETURNS SETOF RECORD AS
$$
  SELECT 1, 'fred'::varchar(300);
$$
LANGUAGE SQL;

regress=# SELECT * FROM something123_legacy('blah') somethingresult(col1name integer, col2name character varying(300));
 col1name | col2name 
----------+----------
        1 | fred
(1 row)

或者,您可以CREATE TYPE创建定义的行类型,或使用现有的表类型,因为每个表都有一个同名的行类型。然后,您的函数可以返回该行类型。

regress=# CREATE TYPE something123type AS (col1name integer, col2name character varying(300));
CREATE TYPE
regress=# CREATE FUNCTION something123_legacy2(character varying(100))
    RETURNS SETOF something123type AS
    $$
      SELECT 1, 'fred'::varchar(300);
    $$
    LANGUAGE SQL;
CREATE FUNCTION
regress=# SELECT * FROM something123_legacy2('blah');
 col1name | col2name 
----------+----------
        1 | fred
(1 row)

您也可以尝试使用OUT参数,但我似乎隐约记得它们仅支持 PL/PgSQL(而不是 SQL 函数)在某一时刻,我不确定它们在 8.1 中是否有效。试试看:

CREATE FUNCTION something123( IN character varying(100), OUT integer, OUT character varying(300) ) RETURNS setof record AS
$$
  SELECT b.year, p.materialUsed FROM bestBefore b join packaged p on b.id=p.id WHERE id=$1;
$$
LANGUAGE SQL;

警告您的 PostgreSQL 版本不受支持,并且已经使用了两年。它没有得到安全或错误修复。最终你将不得不升级,你等待的时间越长,它就会变得越难。立即开始计划您的升级。阅读您和当前版本之间的每个 .0 版本(8.2.0、8.3.0 等)的发行说明,特别注意升级说明和兼容性说明。注意删除对文本的隐式强制转换、bytea_output 更改和standard_conforming 字符串更改。阅读新版本手册的升级部分,并注意使用新版本的pg_dump.

于 2012-10-24T08:17:39.983 回答