PostgreSQL:"refcursor" 处或附近的语法错误
PostgreSQL: syntax error at or near "refcursor"
当我使用 Microsoft SQL 服务器数据库时,我有时 return 来自存储过程的多个结果集。我经常 return 太多以至于很难分辨哪个是哪个。为了解决这个问题,我遵循了一个从同事那里学到的约定:第一个结果集是一个“映射”,它定义了第二个和其他结果集的名称。它只有一条记录,其中每个字段名都是结果集的名称,对应的字段值是它在 returned 结果集数组中的索引。客户端代码首先通过名称查找索引来访问特定的结果集。
下面这个简单的例子展示了这个想法:
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)给出了另外 2 个结果集:一个称为“结果”(索引: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 }]
]
我尝试使用官方文档将此技术移植到 PostgreSQL14,尤其是 this page。我想到了这个:
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"
,指的是declare
之后第一行的refcursor
。
您使用了错误的语言声明。您的过程在 plpgsql
中,但您通过顶部的 language sql
语句将其声明为纯 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
解决问题。
当我使用 Microsoft SQL 服务器数据库时,我有时 return 来自存储过程的多个结果集。我经常 return 太多以至于很难分辨哪个是哪个。为了解决这个问题,我遵循了一个从同事那里学到的约定:第一个结果集是一个“映射”,它定义了第二个和其他结果集的名称。它只有一条记录,其中每个字段名都是结果集的名称,对应的字段值是它在 returned 结果集数组中的索引。客户端代码首先通过名称查找索引来访问特定的结果集。
下面这个简单的例子展示了这个想法:
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)给出了另外 2 个结果集:一个称为“结果”(索引: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 }]
]
我尝试使用官方文档将此技术移植到 PostgreSQL14,尤其是 this page。我想到了这个:
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"
,指的是declare
之后第一行的refcursor
。
您使用了错误的语言声明。您的过程在 plpgsql
中,但您通过顶部的 language sql
语句将其声明为纯 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
解决问题。