3

我找到了这篇文章:

http://wiki.postgresql.org/wiki/Return_more_than_one_row_of_data_from_PL/pgSQL_functions

我正在尝试将其用作我的功能的示例。我正在从不同的表中选择不同的列,并尝试返回一组记录。

这是我的代码:

CREATE OR REPLACE FUNCTION get_details_for_widget(widgetid integer)
  RETURNS SETOF widgetdetails AS
$BODY$
DECLARE
    rec widgetdetails %rowtype;

BEGIN

    FOR rec IN (

        SELECT widget_details.id, widget_details.contact_id, widget_details.priority, widget_owner.contact
        FROM widget_details, widget_owner
        WHERE widget_details.rid=widgetid 
        AND widget_details.active_yn = 't'
        AND widget_owner.id=widget_details.contact_id
        Order by widget_details.priority ASC)
    LOOP
       RETURN NEXT rec;
    END LOOP;
END;

$BODY$
  LANGUAGE plpgsql;

当我尝试编译此代码时,我收到“widgetdetails”类型不存在的错误。根据 wiki 中的示例,我将逻辑更改为如下所示:

CREATE OR REPLACE FUNCTION get_details_for_widget(widgetid integer)
  RETURNS SETOF widgetdetails AS
            'SELECT widget_details.id, widget_details.contact_id,      
            widget_details.priority, widget_owner.contact
        FROM widget_details, widget_owner
        WHERE widget_details.rid=widgetid 
        AND widget_details.active_yn = "t"
        AND widget_owner.id=widget_details.contact_id
        Order by widget_details.priority ASC'
$BODY$
DECLARE
    rec widgetdetails %rowtype;

BEGIN

    FOR rec IN (

        SELECT widget_details.id, widget_details.contact_id, widget_details.priority, widget_owner.contact
        FROM widget_details, widget_owner
        WHERE widget_details.rid=widgetid 
        AND widget_details.active_yn = 't'
        AND widget_owner.id=widget_details.contact_id
        Order by widget_details.priority ASC)
    LOOP
       RETURN NEXT rec;
    END LOOP;
END;

$BODY$
  LANGUAGE plpgsql;

它给了我一个错误,上面写着:

ERROR: syntax error at or near "$BODY$

但我似乎看不到/找不到问题。

4

2 回答 2

3

您尝试使用的语法对于 Postgres 来说是陌生的。

您的代码比它需要的要复杂得多。使用一个简单的 SQL 函数:

CREATE OR REPLACE FUNCTION get_details_for_widget(widgetid integer)
  RETURNS TABLE (id int, contact_id int, priority int, contact text)
$func$
   SELECT d.id, d.contact_id, d.priority, o.contact
   FROM   widget_details d
   JOIN   widget_owner   o ON o.id = d.contact_id
   WHERE  d.rid = widgetid   -- where does widgetid come from?
   AND    d.active_yn = 't'
   ORDER  BY d.priority
$func$ LANGUAGE sql

对于这样一个简单的功能,您根本不需要 plpgsql。请改用普通的SQL 函数

使用 定义临时行RETURNS TABLE ()类型。由于您没有提供表定义,因此我对列类型进行了即兴创作。这也适用于 plpgsql 函数。

还:

  • 使用适当的JOIN条件以获得更好的可读性。

  • 使用表别名简化您的查询。

  • 使用的数据类型booleanwidget_details.active_yn

布尔值

正如评论中所阐明的,它已经是一个布尔列。我建议使用TRUE/FALSE而不是字符串文字 't' / 'f' 进行数据输入 - 引用有关布尔类型的手册

关键字TRUEandFALSE是首选(符合 SQL 的)用法。

WHERE子句中,每个表达式都被评估为一个boolean结果。TRUE合格,FALSE或不合格NULL。因此,对于一个boolean类型,您可以简化:

   AND    d.active_yn = TRUE

只是:

   AND    d.active_yn
于 2013-07-08T16:29:04.623 回答
2

为了使用自定义复合类型,您必须首先使用CREATE TYPE.

示例,大致基于您的查询(使用真实数据类型进行更改):

CREATE TYPE widgetdetails AS (
  id INT,
  contact_id INT,
  widget_details INT,
  contact TEXT
);

只有在创建了这个类型之后,这个声明才能被接受:

DECLARE
    rec widgetdetails;
...

同样对于 , 的语法CREATE FUNCTION,坚持你的第一个版本,第二次尝试有严重的问题并且无济于事。

于 2013-07-08T15:53:01.673 回答