Declare and return a custom type in PostgreSQL function

不问归期 提交于 2019-12-10 19:13:02

问题


I found this article:

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

and I'm trying to use it as an example for my function. I am selecting different columns from different tables, and trying to return a set of records.

Here's my code:

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;

When I try to compile this code, I get the error the the type "widgetdetails" does not exist. In line with the example in the wiki, I changed my logic to look like this:

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;

It gives me an error that says:

ERROR: syntax error at or near "$BODY$

But I can't seem to see / find the problem.


回答1:


The syntax you are trying to use is foreign to Postgres.

Your code is much more complicated than it needs to be. Use a simple SQL function:

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

You don't need plpgsql at all for such a simple function. Use a plain SQL function instead.

Define an ad-hoc row type with RETURNS TABLE (). I improvised with the column types since you did not provide your table definitions. This works for plpgsql functions just as well.

Also:

  • Use a proper JOIN condition for better readability.

  • Simplify your query with table aliases.

  • Use the data type boolean for widget_details.active_yn.

Boolean values

As clarified in the comment, it's a boolean column already. I would advice to use TRUE / FALSE instead of the string literals 't' / 'f' for data input - quoting the manual about the boolean type:

The key words TRUE and FALSE are the preferred (SQL-compliant) usage.

In a WHERE clause, every expression is evaluated to a boolean result. TRUE qualifies, FALSE or NULL do not. So, for a boolean type, you can simplify:

   AND    d.active_yn = TRUE

to just:

   AND    d.active_yn



回答2:


In order to use a custom composite type, you have to create it first with CREATE TYPE.

Example, loosely based on your query (to be changed using the real datatypes):

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

Only after having created this type will this declaration be acceptable:

DECLARE
    rec widgetdetails;
...

Also for the syntax of the CREATE FUNCTION, stick to your first version, the second try has serious problems and won't help.



来源:https://stackoverflow.com/questions/17529917/declare-and-return-a-custom-type-in-postgresql-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!