我正在尝试编写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;
objects
和tasks
都是表,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
关键字来指定输出的字段。
答案 0 :(得分:10)
要从返回多个列的函数(实际上是复合类型或行类型)中检索单个列,请使用以下命令调用它:
SELECT * FROM func();
如果您愿意,您也可以只SELECT
一些列,而不是其他列。想象一下这样一个函数(也称为表函数),如表:
SELECT objectid, projectid, title FROM func();
如果您使用 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;