【问题标题】: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 行。

标签: oracle stored-procedures plsql


【解决方案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));
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-04-17
        相关资源
        最近更新 更多