过程中的查询是不是需要游标?
Posted
技术标签:
【中文标题】过程中的查询是不是需要游标?【英文标题】:Are cursors necessary for queries in a procedure?过程中的查询是否需要游标? 【发布时间】:2015-08-14 22:02:24 【问题描述】:我是 Oracle 的新手,我被要求编写一个程序来从表中查询一些数据。我用 2 个参数、一个光标和一个数字构建了它。基本上我有:
PROCEDURE PROC_NAME (
cursor_name IN OUT NOCOPY MY_DEFINED_CURSOR_TYPE,
a_number IN NUMBER);
AS
BEGIN
OPEN CURSOR_NAME FOR
SELECT
column
FROM
table
WHERE
table.dat_value > (SYSDATE - a_number);
END PROC_NAME;
它就像一个魅力,我能够从光标中获取列。我的问题是请求者不想传入游标,他们只想传入数字。我从来没有创建过一个不使用游标来返回查询值的过程,而我看到的示例只是这样做的。这可能吗?
【问题讨论】:
听起来您只是被要求将cursor_name
参数从IN OUT
更改为OUT
。作为文体方面的事情,我会将OUT
参数放在IN
参数之后,但这只是个人喜好。
有多种方法可以返回数据而不是游标。请求者可以指定他们想要返回的内容吗?嵌套表、关联数组、单个标量值、...?
请求者是否习惯了SQL Server?在 SQL Server 中,游标的返回是隐式的,不需要通过参数。
我使用循环和 putline 来输出值,这对于周末的请求者来说似乎已经足够了。看起来他们像变量一样返回值,但查询可以返回超过 1 行。
【参考方案1】:
您可以使用集合:
CREATE PROCEDURE PROC_NAME (
a_number IN NUMBER,
numbers OUT SYS.ODCINUMBERLIST
)
AS
BEGIN
SELECT number_value
BULK COLLECT INTO numbers
FROM table_name
WHERE date_value > (SYSDATE - a_number);
END PROC_NAME;
另外,如果你不想传入一个游标,那么你可以只传一个:
CREATE OR REPLACE PROCEDURE PROC_NAME (
a_number IN NUMBER,
numbers OUT SYS_REFCURSOR
)
AS
BEGIN
OPEN numbers FOR
SELECT number_value
FROM table_name
WHERE date_value > (SYSDATE - a_number);
END PROC_NAME;
【讨论】:
【参考方案2】:改用a function 吗?但这只是与程序输出参数相比的“风格”差异。无论如何,必须隐式传递返回的值(与@ShannonSeverance 指出的 SQL Server 不同)。
function f(
p_days in number
) return my_defined_cursor_type is
v_cur my_defined_cursor_type;
begin
open v_cur for
select
column
from
table
where
table.dat_value > (sysdate - p_days);
return v_cur;
end;
/
用法
declare
v_cur my_defined_cursor_type := f(42);
begin
-- use v_cur as you like
end;
【讨论】:
【参考方案3】:如果您想应用一些 PL/SQL 逻辑,但仍然使用 select 来查询数据(即不传入游标 - 使用 pipelined functions。
需要定义结果行和表的TYPE; FETCH 游标和 PIPE 函数中的结果。
CREATE or replace type MY_DEFINED_ROW_TYPE as object
(
txt VARCHAR2(30)
);
/
create or replace type MY_DEFINED_TABLE_TYPE as table of MY_DEFINED_ROW_TYPE
/
create or replace function FUN_NAME( a_number IN NUMBER) return
MY_DEFINED_TABLE_TYPE
PIPELINED
as
cur MY_DEFINED_CURSOR_TYPE;
v_txt varchar2(30);
begin
OPEN cur
FOR
SELECT
column
FROM table
WHERE table.dat_value > (SYSDATE - a_number);
LOOP
FETCH cur INTO v_txt;
EXIT WHEN cur%NOTFOUND;
pipe row(v_txt);
END LOOP;
return;
end;
/
用法:
select * from table (FUN_NAME(2));
【讨论】:
以上是关于过程中的查询是不是需要游标?的主要内容,如果未能解决你的问题,请参考以下文章