在PostgreSQL中返回QUERY-Record

时间:2012-03-19 11:19:39

标签: sql postgresql types casting plpgsql

我正在尝试编写PostgreSQL函数,该函数在数据库中插入数据,然后接收一些数据并返回它。 这是代码:

CREATE OR REPLACE FUNCTION newTask(projectid api.objects.projectid%TYPE, predecessortaskid api.objects.predecessortaskid%TYPE, creatoruserid api.objects.creatoruserid%TYPE, title api.objects.title%TYPE, description api.objects.description%TYPE, deadline api.objects.deadline%TYPE, creationdate api.objects.creationdate%TYPE, issingletask api.tasks.issingletask%TYPE)
  RETURNS SETOF api.v_task AS
$$
DECLARE
    v_objectid api.objects.objectid%TYPE;
BEGIN
   INSERT INTO api.objects(objectid, projectid, predecessortaskid, creatoruserid, title, description, deadline, creationdate) VALUES (DEFAULT, projectid, predecessortaskid, creatoruserid, title, description, deadline, creationdate)
   RETURNING objectid INTO v_objectid;

   INSERT INTO api.tasks(objectid, issingletask) VALUES (v_objectid, issingletask);
   RETURN QUERY (SELECT * FROM api.v_task WHERE objectid = v_objectid);
END;
$$ LANGUAGE plpgsql;

objectstasks都是表,v_task是一个视图,它是两者的连接。我之后返回刚刚插入的数据的原因是有一些触发器在它上面工作。

到目前为止一切顺利。我使用RETURNS SETOF api.v_task作为我的返回类型和RETURN QUERY (...),因此期望结果看起来像SELECT from v_task(具有相同数据类型的相同列)。但是,真正发生的是(从pgAdmin输出,与node.js-application相同的结果):

SELECT newTask( CAST(NULL AS integer), CAST(NULL AS integer), 1, varchar 'a',varchar 'a', cast(NOW() as timestamp(0) without time zone), cast(NOW() as timestamp(0) without time zone), true);

newtask
api.v_task
--------
"(27,,,1,a,a,"2012-03-19 12:15:50","2012-03-19 12:15:50","2012-03-19 12:15:49.629997",,t)"

而不是几列,输出被强制为一个,用逗号分隔 由于我已经在使用特殊记录类型,因此我无法使用AS关键字来指定输出的字段。

1 个答案:

答案 0 :(得分:10)

调用表函数

要从返回多个列的函数(实际上是复合类型或行类型)中检索单个列,请使用以下命令调用它:

SELECT * FROM func();

如果您愿意,您也可以只SELECT一些列,而不是其他列。想象一下这样一个函数(也称为表函数),如表:

SELECT objectid, projectid, title FROM func();

此处替代:纯SQL

如果您使用 PostgreSQL 9.1或更高版本,您可能会对此变体感兴趣。我使用可写CTE链接INSERT。

可能有人试图将最终的SELECT作为另一个模块添加到CTE,但在这种情况下不起作用,因为新插入的值在同一CTE中的视图中不可见。所以我把它作为一个单独的命令 - 在SELECT

周围没有括号
CREATE OR REPLACE FUNCTION new_task (
    _projectid         api.objects.projectid%TYPE
   ,_predecessortaskid api.objects.predecessortaskid%TYPE
   ,_creatoruserid     api.objects.creatoruserid%TYPE
   ,_title             api.objects.title%TYPE
   ,_description       api.objects.description%TYPE
   ,_deadline          api.objects.deadline%TYPE
   ,_creationdate      api.objects.creationdate%TYPE
   ,_issingletask      api.tasks.issingletask%TYPE)
  RETURNS SETOF api.v_task AS
$func$
DECLARE
   _objectid api.objects.objectid%TYPE;
BEGIN
   RETURN QUERY
   WITH x AS (
      INSERT INTO api.objects
             ( projectid,  predecessortaskid,  creatoruserid,  title
            ,  description,  deadline,  creationdate)
      VALUES (_projectid, _predecessortaskid, _creatoruserid, _title
            , _description, _deadline, _creationdate)
      RETURNING objectid
      )
   INSERT INTO api.tasks
           (objectid,  issingletask)
   SELECT x.objectid, _issingletask
   FROM   x
   RETURNING objectid INTO _objectid;

   RETURN QUERY
   SELECT * FROM api.v_task WHERE objectid = _objectid;
END
$func$ LANGUAGE plpgsql;