PostgreSQL: синтаксическая ошибка в "рефкурсоре" или рядом с ним [дубликат]
Когда я работаю с базами данных Microsoft SQL Server, я иногда возвращаю несколько наборов результатов из хранимых процедур. Я часто возвращаю так много, что становится трудно понять, что есть что. Чтобы решить эту проблему, я следую соглашению, которое я узнал от коллеги: 1-й набор результатов - это «карта», которая определяет имена для 2-го и других наборов результатов. Он имеет единственную запись, где каждое имя поля - это имя набора результатов, а соответствующее значение поля - его индекс в возвращаемом массиве наборов результатов. Клиентский код обращается к определенным наборам результатов, сначала узнавая индекс по имени.
Следующий простой пример демонстрирует идею:
create or alter procedure divide
@a int,
@b int
as
begin
declare
@error int = 0
-- Name-to-index map
select
1 as result,
2 as error
-- Result
if @b = 0
begin
set @error = 1
select
null as result
end
else
begin
select
@a / @b as result
end
-- Error
select
@error as error
end
В этом примере первый набор результатов (индекс: 0) показывает, что есть еще два набора результатов: один называется «результат» (индекс: 1), а другой - «ошибка» (индекс: 2). Оба содержат только одну запись: результат деления и код ошибки соответственно.
Пример звонка №1:
exec divide @a = 91, @b = 13
Наборы результатов в формате JSON:
[
[{ result: 1, error: 2 }],
[{ result: 7 }],
[{ error: 0 }]
]
Пример вызова №2:
exec divide @a = 91, @b = 0
Наборы результатов в формате JSON:
[
[{ result: 1, error: 2 }],
[{ result: null }],
[{ error: 1 }]
]
Я попытался перенести эту технику на PostgreSQL 14, используя официальную документацию и особенно эту страницу . Я придумал это:
create or replace function divide(
a integer,
b integer
)
returns setof refcursor
language sql as
$$
declare
ref1 refcursor;
ref2 refcursor;
ref3 refcursor;
error int := 0;
begin
-- Name-to-index map
open ref1 for select
1 as result,
2 as error;
return next ref1;
-- Result
if b = 0 then
error := 1;
open ref2 for select
null as result;
else
open ref2 for select
a / b as result;
end if;
return next ref2;
-- Error
open ref3 for select
error;
return next ref3;
end;
$$;
К сожалению, я получаю сообщение об ошибке:
syntax error at or near "refcursor"
, ссылаясь на
refcursor
в 1-й строке после
declare
.
1 ответ
Вы использовали неправильную языковую декларацию. Ваша процедура находится в
plpgsql
но вы объявили это простым
sql
через
language sql
заявление вверху.
Замена
create or replace function divide(
a integer,
b integer
)
returns setof refcursor
language sql as
с
create or replace function divide(
a integer,
b integer
)
returns setof refcursor
language plpgsql as
Решает проблему.