RETURN QUERY-запись в PostgreSQL - PullRequest
       26

RETURN QUERY-запись в PostgreSQL

4 голосов
/ 19 марта 2012

Я пытаюсь написать функцию 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 для указания полей моего вывода.

1 Ответ

10 голосов
/ 19 марта 2012

Вызов табличной функции

Чтобы извлечь отдельные столбцы из функции, возвращающей несколько столбцов (фактически составной тип или тип строки), вызовите ее с помощью:

SELECT <b>* FROM </b>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;
...