PostgreSQL 8.1 中的 SQL 函数“RETURNS TABLE”语法错误

Posted

技术标签:

【中文标题】PostgreSQL 8.1 中的 SQL 函数“RETURNS TABLE”语法错误【英文标题】:SQL function "RETURNS TABLE" syntax error in PostgreSQL 8.1 【发布时间】:2012-10-24 08:10:18 【问题描述】:

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

这是一个简单的例子

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

【问题讨论】:

答案已更新以反映版本。特别是在使用真正古老的 PostgreSQL 版本时,例如 8.1(2005 年 11 月发布,2010 年 11 月最终更新),请在所有问题中清楚地提及您的版本。 @CraigRinger 我应该使用 select version();在终端中的 Postgres 或 psql --version 中?为什么它们还是不同的? 他们肯定是不同的。在大多数系统上,它们会产生相同的结果,但SELECT version() 产生 server 版本,而psql --version 打印psql 客户端的版本。完全可以使用(比如说)psql 9.2 连接到 PostgreSQL 8.4,因此版本不一定相同。对于大多数问题,它是您关心的服务器版本,这就是首选select version() 的原因。一些系统(通常是 Mac OS X)经常在它们上面安装多个 PostgreSQL 版本,所以知道它是服务器版本可能很重要。 您应该现在更新到受支持的版本。 @a_horse_with_no_name 这只是一个类,所以我想没有人会打扰它。 【参考方案1】:

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

在非常旧的 PostgreSQL 版本(如 8.1)上,您必须声明 RETURNS SETOF RECORD 而不使用 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;

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

【讨论】:

好的,谢谢,我搞定了。我遇到问题的最后一部分是我想比较输入,所以我选择了“$1”,但我需要删除“”(否则返回 0 行)。因此,如果参数的类型是字符变化,那么在引用它时不需要单引号? @Celeritas ...我不确定你的意思。 '' is different to '$1' is different to $1 如果这就是你要问的;第一个是空字符串,第二个是字符串'$1',另一个扩展为参数。但是你没有在你的问题中写'',我也没有在答案中,所以我不确定你在说什么。你是在问我在上面使用了一个简单的虚拟语句而不是你的 SELECT 语句吗? '因为那只是为了方便测试。

以上是关于PostgreSQL 8.1 中的 SQL 函数“RETURNS TABLE”语法错误的主要内容,如果未能解决你的问题,请参考以下文章

PostgreSQL之SQL函数介绍及实践

PostgreSQL之SQL函数介绍及实践

避免在 django 1.4 和 postgresql 8.1 中使用与 bug #10467 相关的 RETURN postgresql 语句

postgresql database server 8.1 错误1069 怎么回事

使用 SQL 列出 Postgres db 8.1 中的所有序列

如何使用 Play 框架中的演变在 PostgreSQL 中创建函数?