【问题标题】:Getting a Ref Cursor from Custom Cursor Type从自定义光标类型获取参考光标
【发布时间】:2019-09-13 23:26:07
【问题描述】:

我们有一个名为“Get()”的现有 PL SQL 过程,当提供一个 order_no_ 和一个 sequence_no_ 时,它返回一个名为“CURSOR_TYPE”的命名 REF CURSOR 类型。我需要对此方法进行“重载”,程序员只需传入 order_no_(无 sequence_no_),它会重复调用该方法并将所有 sequence_no_ 值的所有记录收集到单个返回“CURSOR_TYPE”REF CURSOR 中。以下是我为实现这一目标而写的内容,并尝试遵循示例shown here

    PROCEDURE Get(order_no_ IN VARCHAR2, results_cursor OUT CURSOR_TYPE)
    AS
    --Declare a "nested table type" table
    TYPE CoC_RowType IS TABLE OF customer_order_charge_cfv%ROWTYPE; 
    CoC_RowTable CoC_RowType := CoC_RowType();
    CURSOR c1 IS
      SELECT coc.SEQUENCE_NO
      FROM customer_order_charge_cfv coc
      WHERE coc.ORDER_NO = order_no_;
    BEGIN
    FOR i in c1 LOOP
        CoC_RowTable.extend();
        Get(order_no_, i.sequence_no, results_cursor);
        FETCH results_cursor INTO CoC_RowTable(CoC_RowTable.count);
    END LOOP;

    OPEN results_cursor FOR SELECT * FROM TABLE(CoC_RowTable);

    END Get;

但是,当我尝试将此代码编译到我的包中时,我收到以下错误:

    Compilation errors for PACKAGE BODY GLOB1APP.GFS_CUSTOMER_ORDER_CHARGE_CFP

    Error: PLS-00382: expression is of wrong type
    Line: 81
    Text: OPEN results_cursor FOR SELECT * FROM TABLE(CoC_RowTable);

    Error: PL/SQL: ORA-22905: cannot access rows from a non-nested table item
    Line: 81
    Text: OPEN results_cursor FOR SELECT * FROM TABLE(CoC_RowTable);

    Error: PL/SQL: SQL Statement ignored
    Line: 81
    Text: OPEN results_cursor FOR SELECT * FROM TABLE(CoC_RowTable);

这行似乎出错了:

    OPEN results_cursor FOR SELECT * FROM TABLE(CoC_RowTable);

我做错了什么?我怎样才能实现我的目标?这完全是错误的途径吗?

【问题讨论】:

  • 您是否调查过您遇到的错误?有许多问题和答案说明您不能在这样的 SQL 查询中使用 PL/SQL 集合类型。您是否能够改为创建模式级对象和表类型? (正如您链接到的问题的公认答案一样;评论指的是并不总是可取的......)
  • @AlexPoole 对于此更改的要求,我不允许创建任何架构级别的对象/类型,所有内容都必须在此包/方法的范围内。
  • 那你恐怕有点卡住了。您将不得不让这个程序复制原始程序正在执行的操作,只是没有序列号。这对于可维护性来说不是好消息,但对于性能来说可能是个好消息。
  • @AlexPoole 谢谢,这就是我害怕的 - 必须复制并粘贴原始的 Get() 方法并修改其 where 子句......我想通过重载来避免这种情况,就像你说,为了提高可维护性......但如果你说如果不创建新的模式级对象就不可能实现这个目标......那么呃......我想我必须做我所拥有的要做...感谢您的帮助。

标签: oracle plsql oracle11g ref-cursor rowtype


【解决方案1】:

为什么不改变现有的过程和查询两者都做呢?简单例子:

SQL> create table customer_order_charge_cfv(
  2    order_no number,
  3    sequence_no number
  4  );

Table CUSTOMER_ORDER_CHARGE_CFV created.

SQL> insert into customer_order_charge_cfv
  2  select 1,1 from dual union all
  3  select 1,2 from dual;

2 rows inserted.

SQL> create or replace PROCEDURE Get(
  2    order_no_ IN VARCHAR2, 
  3    sequence_no_ IN VARCHAR2 default null, 
  4    results_cursor OUT SYS_REFCURSOR
  5  ) AS
  6  BEGIN
  7  OPEN results_cursor FOR 
  8    SELECT *
  9    FROM customer_order_charge_cfv coc
 10    WHERE coc.ORDER_NO = order_no_
 11    and (coc.sequence_no = sequence_no_ or sequence_no_ is null);
 12  END Get;
 13  /

Procedure GET compiled

SQL> var rc refcursor;

SQL> exec get(1,2,:rc);

PL/SQL procedure successfully completed.


SQL> print :rc;

  ORDER_NO SEQUENCE_NO
---------- -----------
         1           2

SQL> exec get(1,results_cursor => :rc);

PL/SQL procedure successfully completed.

SQL> print :rc;

  ORDER_NO SEQUENCE_NO
---------- -----------
         1           1
         1           2

问候, 炖菜

【讨论】:

  • 完美!我没有考虑为“替代版本”设置序列号的默认值并匹配空值。这应该很好用,谢谢!
【解决方案2】:

Oracle中有两种“类型”的TYPE:

SQL 类型,由 SQL 语句创建:

CREATE OR REPLACE TYPE...
/

和 PL/SQL 类型,在 PL/SQL 代码中声明。

您正试图在 SQL 语句中使用 PL/SQL 类型。 SQL 语句只知道 SQL 类型。您要么必须创建一个 SQL“对象”类型,然后是该对象的 SQL“表”类型,要么做一些不同的事情。

此外,REF CURSOR 的工作方式与您的代码试图使其工作的方式不同。您需要执行 一个 SQL 查询,该查询返回与所有这些 GET() 调用相同的数据,然后返回该查询的游标而不进行任何获取。客户端进行获取。

要获得更多详细信息,请发布 CURSOR_TYPE 的定义并显示 GET() 实际查询的内容。

这取决于您的回答是否容易。

最好的问候, 炖阿什顿

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-05-03
    • 2010-12-10
    • 1970-01-01
    • 1970-01-01
    • 2013-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多