【问题标题】:How to fetch a ref_cursor into Oracle's WITH CLAUSE如何在 Oracle WITH CLAUSE 中获取引用游标
【发布时间】:2017-08-04 04:10:31
【问题描述】:

是否可以在 ORACLE WITH CLAUSE 中使用 ref_cursor。例如,我有以下场景。首先我有一个返回 ref_cursor 的过程

PROCEDURE p_return_cursor(p_id IN NUMBER, io_cursor OUT t_cursor) 
AS
BEGIN
  OPEN io_cursor FOR
    SELECT col1, col2 
      FROM Table1 t 
     WHERE t.id = p_id;
END;

其次,我有另一个过程调用 p_return_cursor:

PROCEDURE p_test(p_cid IN NUMBER)
AS
  l_cursor t_cursor;
  l_rec Table1%ROWTYPE;
BEGIN
  p_return_cursor(p_id => p_cid, io_cursor => l_cursor);
  -- CODE GOES HERE
...

现在,我的问题是,我可以使用 Oracle 的 WITH CLAUSE 使用游标创建一个临时表吗?类似:

...
  WITH data AS (
    LOOP
      FETCH l_cursor INTO l_rec;
      EXIT WHEN l_cursor%NOTFOUND;
        SELECT l_rec.col1, l_rec.col2 FROM DUAL;
    END LOOP;
    CLOSE l_cursor;
    )

【问题讨论】:

  • WITHSQL 的一部分,而不是PL/SQL

标签: oracle plsql


【解决方案1】:

你不能直接这样做。但是,您可以将光标 BULK COLLECT 放入 PL/SQL 表变量中,并在 WITH 子句中使用 that

如果游标包含许多行,请注意内存使用情况。

完整示例:

CREATE TABLE table1 ( col1 NUMBER, col2 NUMBER );

INSERT INTO table1 ( col1, col2 ) SELECT rownum, 100+rownum FROM DUAL CONNECT BY ROWNUM <= 15;

COMMIT;

CREATE OR REPLACE PACKAGE se_example AS

  TYPE t_cursor IS REF CURSOR
    RETURN table1%ROWTYPE;

  TYPE l_rec_tab IS TABLE OF table1%ROWTYPE;


  PROCEDURE p_test (p_cid IN NUMBER);
END se_example;



CREATE OR REPLACE PACKAGE BODY se_example AS
  -- private
  PROCEDURE p_return_cursor (p_id IN NUMBER, io_cursor OUT t_cursor) AS
  BEGIN
    OPEN io_cursor FOR
      SELECT col1,
             col2
      FROM   table1 t; 
      --WHERE  t.id = p_id;  -- I didn't put "id" column in my sample table, sorry...
  END p_return_cursor;

  PROCEDURE p_test (p_cid IN NUMBER) IS
    l_cursor   t_cursor;
    l_tab      l_rec_tab;
    l_dummy    NUMBER;
  BEGIN
    p_return_cursor (p_id => p_cid, io_cursor => l_cursor);

    FETCH l_cursor BULK   COLLECT INTO l_tab;

  -- *** instead of this    

  --  WITH data AS (
  --    LOOP
  --      FETCH l_cursor INTO l_rec;
  --      EXIT WHEN l_cursor%NOTFOUND;
  --        SELECT l_rec.col1, l_rec.col2 FROM DUAL;
  --    END LOOP;
  --    CLOSE l_cursor;
  --    )
  --    '
  --

  -- *** do this    

    WITH data AS 
      ( SELECT col1, col2 FROM TABLE(l_tab) )
    SELECT sum(col1 * col2) INTO l_dummy
    FROM data;

    dbms_output.put_line('result is ' || l_dummy);

  END p_test;
END se_example;


begin
  se_example.p_test(100);
end;

【讨论】:

  • 不错!非常感谢你的帮助。我实现了上述代码,但出现错误:PACKAGE BODY WEBLOSSRT.JNS_TEST Error: PLS-00642: local collection types not allowed in SQL statements Line: 49 Text: ( SELECT col1, col2 FROM TABLE(l_tab) ) Error: PL/SQL: ORA-22905: cannot access rows from a non-nested table item Line: 49 Text: ( SELECT col1, col2 FROM TABLE(l_tab) ) Error: PL/SQL: SQL Statement ignored Line: 48 Text: WITH data AS 的编译错误
  • 您使用的是哪个版本的 Oracle?我写的内容只能在 12c 中使用。在早期版本中,您需要将 TYPE 从包规范中移出,并通过 CREATE TYPE 命令将其替换为数据库对象类型。
  • 哦,我明白了。好吧,我们正在使用 Oracle v11。但是谢谢,这种方法正是我想要的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-13
  • 1970-01-01
  • 2023-02-03
  • 2013-12-23
相关资源
最近更新 更多