过程中的查询是不是需要游标?

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));

【讨论】:

以上是关于过程中的查询是不是需要游标?的主要内容,如果未能解决你的问题,请参考以下文章

mysql游标的用法及作用

MySQL从入门到精通50讲(二十一)-CURSOR游标

MySQL从入门到精通50讲(二十一)-CURSOR游标

Oracle使用存储过程返回查询游标

cursor游标(mysql)

sql 知道父节点,查询所有的子节点,运用游标,递归,存储过程