PostgreSQL 11 — Процедуры

С последним обновлением процедур поддержки PostgreSQL. Официальный блог цитирует "В отличие от функций процедуры не обязаны возвращать значение" (https://blog.2ndquadrant.com/postgresql-11-server-side-procedures-part-1/)

Итак, мой вопрос: есть ли способ вернуть код ошибки или ответ в процедуре? (Процедуры появились в Postgres относительно недавно, поэтому онлайн-ресурсов было очень мало.)

Вот пример того, что я имел в виду, возвращая эти «коды ошибок».

create or replace PROCEDURE multislot_Update_v1
(
  p_id in varchar2,
  p_name in varchar2,
  p_enname in varchar2,
  results out SYS_REFCURSOR
) AS
rowNumber int;
defaultNumber int;
BEGIN

   select count(1) into rowNumber from MULTISLOTSGAME where fid=P_id;

    if (rowNumber = 0) then
      open results for
      select '1' as result from dual;
      return;
    end if;

  update MULTISLOTSGAME  set
    name = P_name,
    enname = P_enname
  where fid = P_id ;
  commit;

 open results for
  select '0' as result, t1.* from MULTISLOTSGAME t1 where fid = p_id;

END multislot_Update_v1;

Приведенный выше сценарий является процедурой Oracle, как вы можете видеть, если возвращенный результат равен «1», это означает, что обновление не было успешным.

Можно ли как-нибудь написать приведенный выше скрипт (с кодом ошибки) как процедуру PostgresSQL? Возможно, пример использования аргумента «INOUT» был бы отличным!


person deviantxdes    schedule 20.06.2018    source источник
comment
Postgres не различает функцию и процедуру. По сути, вы можете написать функцию, которая все это (обновляет/вставляет и т. д.), и использовать select для ее запуска в области sql, внутри транзакции или использовать perform для ее запуска внутри блока plpgsql. Вот пример функции, которая возвращает refcursor: stackoverflow.com/questions/6674787/   -  person Kaushik Nayak    schedule 20.06.2018
comment
спасибо за ваш вклад, я уже могу запустить функцию, которая возвращает refcuror, используя SELECT ‹function›. Кстати, процедура использует CALL ‹процедуру›, и синтаксис в сценарии создания процедуры отличается от функции   -  person deviantxdes    schedule 20.06.2018
comment
@KaushikNayak: Postgres 11 будет различать функции и процедуры.   -  person a_horse_with_no_name    schedule 20.06.2018
comment
@a_horse_with_no_name : Не знал этого. Спасибо за информацию. я новичок в постгресе   -  person Kaushik Nayak    schedule 20.06.2018


Ответы (2)


В процедуре может быть INOUT параметров.

Вы вызываете процедуру с помощью оператора CALL; если есть какие-либо параметры INOUT, оператор вернет строку результата точно так же, как SELECT.

Вот пример, в котором используется процедура, возвращающая refcursor:

CREATE PROCEDURE testproc(INOUT r refcursor) LANGUAGE plpgsql AS
$$BEGIN
   r := 'cur';
   OPEN r FOR VALUES (1), (42), (12321);
END;$$;

BEGIN;

CALL testproc(NULL);

  r  
-----
 cur
(1 row)

FETCH ALL FROM cur;

 column1 
---------
       1
      42
   12321
(3 rows)

COMMIT;
person Laurenz Albe    schedule 20.06.2018
comment
Хм, вы можете построить пример? в официальном документе было упомянуто, что (аргументы OUT в настоящее время не поддерживаются для процедур. Вместо этого используйте INOUT.). - person deviantxdes; 20.06.2018
comment
Истинный; Я удалил ссылку на INOUT параметры. О примерах: это работает так же, как и сегодня в функциях. - person Laurenz Albe; 20.06.2018
comment
спасибо за ваш вклад, у вас есть идеи, поддерживает ли INOUT тип refcursor? Для функций, которые были бы, например. Рекурсор результатов OUT - person deviantxdes; 20.06.2018
comment
а также как будет выполняться процедура с inout refcursor? Вызов ‹процедуры›('refcuror') - person deviantxdes; 20.06.2018
comment
Я добавил пример, который должен показать вам, как это работает. - person Laurenz Albe; 20.06.2018
comment
Спасибо за пример, очень ценю. Могу я узнать, какую IDE вы используете для выполнения процедуры? я использую DBeaver, и кажется, что CALL testproc(null); вообще не возвращает никаких результатов/refcursor. Таким образом, невозможно выполнить выборку всего в .. - person deviantxdes; 20.06.2018
comment
Моя IDE — psql, и я могу только рекомендовать ее. Оператор определенно должен возвращать строку, как это сделал бы оператор SELECT. Вы используете v11? FETCH должен работать, даже если вы не видите результата (это всегда будет cur). - person Laurenz Albe; 20.06.2018
comment
Ого, это действительно работает с psql ... @Laurenz Albe, могу ли я спросить, могут ли ЗНАЧЕНИЯ быть строкой / записью вместо числа / строки, например. OPEN r для значений (выберите fid,fname из user_player limit 1); - person deviantxdes; 20.06.2018
comment
Да, вы можете это проверить. - person Laurenz Albe; 20.06.2018
comment
Как я могу прочитать несколько значений INOUT? скажем, у меня есть страница INOUT bigint и refcursor результатов INOUT. . Вызов FETCH ALL IN cur; возвращает мне только то, что находится в refcursor, как я могу получить значения страницы вместе? - person deviantxdes; 21.06.2018
comment
Я не понимаю этот вопрос. Вы получаете оба параметра INOUT в строке результата из оператора CALL. Поиграйте с ним, вы увидите, что это просто. - person Laurenz Albe; 21.06.2018
comment
Извините за плохой вопрос, это пример создания скрипта CREATE OR REPLACE PROCEDURE pg_player_get_by_id3 (IN pid character, INOUT page bigint, INOUT results refcursor) ..... как я могу прочитать вывод "page", а также "results" ' ? Я попытался вызвать FETCH ALL IN cur, но он не показывает вывод для «страницы». - person deviantxdes; 21.06.2018
comment
Нет. Прежде чем FETCH, вы должны CALL пройти процедуру, верно? И этот CALL вернет как page, так и results. Я считаю, что это всего лишь мысли с вашей стороны. - person Laurenz Albe; 21.06.2018

Как насчет использования оператора RAISE?

https://www.postgresql.org/docs/10/static/plpgsql-errors-and-messages.html

person isapir    schedule 20.06.2018
comment
Не все ответы являются ошибкой/исключением, могут быть сценарии, в которых мне нужно вернуть количество затронутых строк и т. д. - person deviantxdes; 20.06.2018