无法打印引用光标

时间:2016-06-02 14:43:12

标签: oracle sqlplus sys-refcursor

我无法打印从过程打开的引用游标:

var imgs = document.getElementsByTagName('img');
for(i = 0; i< imgs.length; i++)
{
    attachMyLoadEvent(imgs[i]);
}

function attachMyLoadEvent(img)
{
    img.onload = function(){console.log('img loaded: ' + img.src);};
}

编译没有错误但是当我调用它时我无法打印OUT参数值:

CREATE OR REPLACE PROCEDURE RMAN_COMMON.backup_report(P_OUT OUT sys_refcursor)
is
--P_OUT SYS_REFCURSOR;
NAME varchar2(100) ;

cursor c1
is
select owner || '.' || VIEW_NAME as NAME 
from  dba_views  
where owner like 'RMAN_%' 
and owner  !='RMAN_COMMON' 
and VIEW_NAME ='RC_RMAN_BACKUP_JOB_DETAILS';

BEGIN
    for rec1 in c1     
     Loop
fetch c1 into NAME;       
           OPEN P_OUT FOR 'SELECT db_name, start_time, end_time, input_type, status, time_taken_display, output_bytes_display, output_device_type FROM ' || NAME;

     close P_OUT;
     end loop;
end;
/

3 个答案:

答案 0 :(得分:0)

ORA-24338错误是因为您在程序中关闭了p_out;从循环中删除该行

仍然必须打开引用游标,客户端才能使用它。它会一直打开,直到客户端会话结束或明确关闭它。

您的显式游标c1也可能永远不会找到任何行,在这种情况下它永远不会打开,这也会在SQL * Plus中得到相同的错误。假设确实存在至少一个匹配视图,那么多次打开引用游标(如果有多个视图,具有不同的所有者)并不是真的有意义,所以你也可以在第一次获取后退出。

在循环内明确获取也是不对的;虽然如果你真的这样做,你会得到ORA-01001: invalid cursor

所以你可以这样做:

...
begin
    for rec1 in c1 loop
      open p_out for 'SELECT db_name, start_time, end_time, input_type, status, time_taken_display, output_bytes_display, output_device_type FROM '
        || rec1.NAME;
      exit; -- or return since you don't do anything after the loop
    end loop;
end;
/

或者避免循环并对变量进行单次提取:

...
begin
    open c1;
    fetch c1 into NAME;
    open p_out for 'SELECT db_name, start_time, end_time, input_type, status, time_taken_display, output_bytes_display, output_device_type FROM '
      || NAME;
    close c1;
end;
/

答案 1 :(得分:0)

问题在于错误的PL / SQL过程。 forfetch不兼容,您不能同时使用这两者。此外,您无法在返回之前关闭光标,否则它将无法使用。

以下是正确程序的示例:

CREATE OR REPLACE PROCEDURE backup_report(P_OUT OUT sys_refcursor) IS
BEGIN

    FOR rec1 IN (
        SELECT owner || '.' || view_name AS name 
        FROM  dba_views  
        WHERE owner LIKE 'RMAN_%' 
        AND owner  !='RMAN_COMMON' 
        AND VIEW_NAME ='RC_RMAN_BACKUP_JOB_DETAILS';
    ) LOOP
           OPEN P_OUT FOR 'SELECT * FROM ' || rec1.NAME;
           RETURN;
     END LOOP;
END;

答案 2 :(得分:0)

我根据你的答案重写代码。它现在更好,但我只从一个表RMAN_B2ETEST.RC_RMAN_BACKUP_JOB_DETAILS获得输出。动态表名是关键,我必须有一个循环。

CREATE OR REPLACE函数RMAN_COMMON.backup_report return sys_refcursor是

P_OUT SYS_REFCURSOR;

V_OWNER dba_views.owner%type; V_VIEW_NAME dba_views.view_name%type;

光标c1 是 从dba_views中选择所有者,VIEW_NAME作为NAME,其中所有者为“RMAN_%”和所有者!='RMAN_COMMON'和VIEW_NAME ='RC_RMAN_BACKUP_JOB_DETAILS';

BEGIN 打开c1; 将c1提取到V_OWNER,V_VIEW_NAME;

OPEN P_OUT FOR'SELECT db_name,start_time,end_time,input_type,status,time_taken_display,output_bytes_display,output_device_type FROM'|| V_OWNER || '' || V_VIEW_NAME; 返回P_OUT;

关闭c1;

端; /

从dual选择backup_report();

。 。 。 。 B2ETEST 25-APR-16 25-APR-16 DB完全完成00:13:08 57.79G SBT_TAPE B2ETEST 15-MAY-16 15-MAY-16 DB FULL COMPLETED 00:10:29 58.41G SBT_TAPE B2ETEST 18-MAY-16 18-MAY-16 DB FULL COMPLETED 00:35:14 58.42G SBT_TAPE B2ETEST 02-JUN-16 02-JUN-16 DB FULL COMLETED 00:08:09 58.94G SBT_TAPE B2ETEST 11-MAR-16 11-MAR-16 DB FULL COMPLETED 00:10:36 56.02G SBT_TAPE B2ETEST 27-MAR-16 27-MAR-16 DB FULL COMPLETED 00:10:37 56.36G SBT_TAPE B2ETEST 29-MAR-16 29-MAR-16 DB FULL COMPLETED 00:10:41 56.36G SBT_TAPE B2ETEST 31-MAR-16 31-MAR-16 DB FULL COMPLETED 00:12:23 56.95G SBT_TAPE B2ETEST 02-APR-16 02-APR-16 DB FULL COMPLETED 00:12:53 57.05G SBT_TAPE B2ETEST 24-APR-16 24-APR-16 DB完全完成00:11:11 57.78G SBT_TAPE B2ETEST 29-APR-16 29-APR-16 DB完全完成00:11:40 58.04G SBT_TAPE

DB_NAME START_TIM END_TIME INPUT_TYPE状态TIME_TAKEN_DISPLAY OUTPUT_BYTES_DISPLAY OUTPUT_DEVICE_TYP

B2ETEST 04-MAY-16 04-MAY-16 DB FULL COMPLETED 00:14:54 58.06G SBT_TAPE

选择了78行。