我发现这篇文章:
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$
但我似乎看不到/发现问题。
您尝试使用的语法对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函数。
RETURNS TABLE ()
还:
使用适当的JOIN条件以获得更好的可读性。
JOIN
使用表别名简化查询。
将数据类型boolean用于widget_details.active_yn。
boolean
widget_details.active_yn
如评论中所阐明的,它已经是一个布尔列。我建议使用TRUE/FALSE代替字符串文字’t’/’f’进行数据输入- 引用有关布尔类型的手册:
TRUE
FALSE
关键字TRUE和FALSE是首选(与SQL兼容)的用法。
在WHERE子句中,每个表达式都将求值为boolean结果。TRUE合格FALSE或不合格NULL。因此,对于boolean类型,您可以简化:
WHERE
NULL
AND d.active_yn = TRUE
只是:
AND d.active_yn