使用显式游标时,SYS_REFCURSOR不起作用

时间:2019-06-26 11:46:25

标签: sql oracle plsql oracle12c

我们有一个现有的程序包,可以将数据插入存储在远程数据库(SQL Server)中的表中。以下是该软件包的摘要:

CREATE OR REPLACE PACKAGE XXMyPackage
AS

  PROCEDURE GiveMyCursor;

END XXMyPackage;
/

CREATE OR REPLACE PACKAGE BODY XXMyPackage
AS

  PROCEDURE GiveMyCursor IS

    cursor cursor_1 is
    SELECT 'really long query with a lot of joined tables'  column1
        ,  'this is an existing code'                       column2
        ,  'i cannot modify this'                           column3
    from   dual;

  BEGIN

    for cursor_x in cursor_1 loop
        sql_stmt := 'insert into some_remote_table (column1, column2, column3, column4, column5)'||
        'values (:1,    0,    :2,    :3,    0) ';
        EXECUTE IMMEDIATE sql_stmt
        USING trim(cursor_x.column1),
        trim(cursor_x.column2),
        trim(cursor_x.column3);
        l_count := get_records_for_insert%rowcount;
    end loop;

  END GiveMyCursor;

END XXMyPackage;
/

我的任务是通过在插入后将其内容转储到目录中的XLSX文件中来为此程序包添加功能。 另外,我应该对现有代码进行很少的修改,并使代码尽可能短。 我可以通过以下修改来做到这一点(注意带有“添加的”注释的行:

CREATE OR REPLACE PACKAGE XXMyPackage
AS

  TYPE refMyCursor IS REF CURSOR RETURN curMyCursor%ROWTYPE;    -- added
  TYPE typMyCursor IS TABLE OF curMyCursor%ROWTYPE;             -- added

  PROCEDURE GiveMyCursor;

END XXMyPackage;
/

CREATE OR REPLACE PACKAGE BODY XXMyPackage
AS

  PROCEDURE GiveMyCursor IS

    pCursor         SYS_REFCURSOR;                                      -- added
    l_directory     DBA_DIRECTORIES.DIRECTORY_NAME%TYPE := 'DATA_DIR';  -- added
    l_filename      VARCHAR2(250) := 'SAMPLE_FILENAME';                 -- added

    cursor cursor_1 is
    SELECT 'really long query with a lot of joined tables'  column1
        ,  'this is an existing code'                       column2
        ,  'i cannot modify this'                           column3
    from   dual;

  BEGIN

    for cursor_x in cursor_1 loop
        sql_stmt := 'insert into some_remote_table (column1, column2, column3, column4, column5)'||
        'values (:1,    0,    :2,    :3,    0) ';
        EXECUTE IMMEDIATE sql_stmt
        USING trim(cursor_x.column1),
        trim(cursor_x.column2),
        trim(cursor_x.column3);
        l_count := get_records_for_insert%rowcount;
    end loop;

    /* **************** Start of added Code  **************** */
    -- cursor query was re-used
    OPEN pCursor FOR 
    SELECT 'really long query with a lot of joined tables'  column1
        ,  'this is an existing code'                       column2
        ,  'i cannot modify this'                           column3
    from   dual;

    l_filename := l_filename||'_'||TO_CHAR(SYSDATE, 'DDMMYYYYHHMISS')||'.xlsx';

    -- dumps the query results into an xlsx file
    as_xlsx.query2sheet( p_cur          => pCursor      -- Uses Sys_RefCursor
                       , p_sheetname    => l_filename   -- This is where we assign the Sheet Names
                       , p_directory    => l_directory  -- Saves it into the directory
                       , p_filename     => l_filename   -- The filename of the xlsx file
                       );                       

    /* **************** End of added Code **************** */

  END GiveMyCursor;

END XXMyPackage;
/

注意:软件包as_xlsx是从另一个SO帖子(Create an Excel File (.xlsx) using PL/SQL)提取的

我已经确认修改后的程序包可以工作,并且在匿名块中运行XXMyPackage.GiveMyCursor时可以在目录中看到该文件。但是,cursor_1非常长,已被重新用于打开SYS_REFCURSOR pCursor。我尝试将其缩短,以便进一步修改代码以使其:

CREATE OR REPLACE PACKAGE XXMyPackage
AS
    /* **************** Start of added Code **************** */
    cursor cursor_1 is
    SELECT 'really long query with a lot of joined tables'  column1
        ,  'this is an existing code'                       column2
        ,  'i cannot modify this'                           column3
    from   dual;    

    TYPE typMyCursor IS TABLE OF cursor_1%ROWTYPE;      
    /* **************** End of added Code **************** */

    PROCEDURE GiveMyCursor;

END XXMyPackage;
/

CREATE OR REPLACE PACKAGE BODY XXMyPackage
AS

  PROCEDURE GiveMyCursor IS

    tabMyCursor     typMyCursor;                                        -- added        
    pCursor         SYS_REFCURSOR;                                      -- added
    l_directory     DBA_DIRECTORIES.DIRECTORY_NAME%TYPE := 'DATA_DIR';  -- added
    l_filename      VARCHAR2(250) := 'SAMPLE_FILENAME';                 -- added

  BEGIN

    for cursor_x in cursor_1 loop
        sql_stmt := 'insert into some_remote_table (column1, column2, column3, column4, column5)'||
        'values (:1,    0,    :2,    :3,    0) ';
        EXECUTE IMMEDIATE sql_stmt
        USING trim(cursor_x.column1),
        trim(cursor_x.column2),
        trim(cursor_x.column3);
        l_count := get_records_for_insert%rowcount;
    end loop;

    /* **************** Start of added Code **************** */
    OPEN cursor_1;
    FETCH cursor_1 BULK COLLECT INTO tabMyCursor;  
    CLOSE cursor_1;

    OPEN pCursor FOR
    SELECT  *
    FROM    TABLE(tabMyCursor);

    l_filename := l_filename||'_'||TO_CHAR(SYSDATE, 'DDMMYYYYHHMISS')||'.xlsx';

    -- dumps the query results into an xlsx file
    as_xlsx.query2sheet( p_cur          => pCursor      -- Uses Sys_RefCursor
                       , p_sheetname    => l_filename   -- This is where we assign the Sheet Names
                       , p_directory    => l_directory  -- Saves it into the directory
                       , p_filename     => l_filename   -- The filename of the xlsx file
                       );                       

    /* **************** End of added Code **************** */

  END GiveMyCursor;

END XXMyPackage;
/

但是,当我这样做时,在匿名块中运行No more data to read from socket几秒钟后,我得到了错误XXMyPackage.GiveMyCursor。造成此错误的原因是什么?

数据库版本:

Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
PL/SQL Release 12.1.0.2.0 - Production
"CORE   12.1.0.2.0  Production"
TNS for Linux: Version 12.1.0.2.0 - Production
NLSRTL Version 12.1.0.2.0 - Production

0 个答案:

没有答案