一尘不染

在PostgreSQL函数中声明并返回自定义类型

sql

我发现这篇文章:

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$

但我似乎看不到/发现问题。


阅读 293

收藏
2021-03-08

共1个答案

一尘不染

您尝试使用的语法对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条件以获得更好的可读性。

  • 使用表别名简化查询。

  • 将数据类型boolean用于widget_details.active_yn

布尔值

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

关键字TRUEFALSE是首选(与SQL兼容)的用法。

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

   AND    d.active_yn = TRUE

只是:

   AND    d.active_yn
2021-03-08