PL/SQL: ORA-29481: 隐式结果不能返回给客户端

Posted

技术标签:

【中文标题】PL/SQL: ORA-29481: 隐式结果不能返回给客户端【英文标题】:PL/SQL: ORA-29481: Implicit results cannot be returned to client 【发布时间】:2016-11-15 21:15:11 【问题描述】:

我已经将下面的过程 mysql 迁移到了 ORACLE,下面也给出了迁移的版本。 迁移过程已成功编译,但是当我们在 SQL Developer 中使用相应参数运行此过程以打印“v_refcur”SYS_REFCURSOR 结果时 它给了我错误:ORA-29481:无法将隐式结果返回给客户端

--- 源 Mysql 过程--------------------------------------------

DROP PROCEDURE IF EXISTS  `get_police_station_for_hierarchy` ;

DELIMITER $$

 CREATE  PROCEDURE `get_police_station_for_hierarchy`(officecd BIGINT,pstsaffcd VARCHAR(20))
BEGIN
DECLARE table_count INT;
DECLARE officerInCharge VARCHAR(20);
DROP TEMPORARY TABLE IF EXISTS   temp1;
DROP TEMPORARY TABLE IF EXISTS   temp2;
DROP TEMPORARY TABLE IF EXISTS  temp3;
DROP TEMPORARY TABLE IF EXISTS  temp4;
CREATE TEMPORARY TABLE temp1 (cd BIGINT,off_level INT);
CREATE TEMPORARY TABLE temp2 (cd BIGINT,off_level INT);
CREATE TEMPORARY TABLE temp3 (cd BIGINT,off_level INT);
CREATE TEMPORARY TABLE temp4 (cd BIGINT,off_level INT);

 SELECT OFFICE_INCHARGE_CD INTO officerInCharge FROM m_office_types  WHERE OFFICE_CD=officecd ;
 IF(officerInCharge=pstsaffcd) THEN
INSERT INTO temp1 
SELECT m_office_hierarchy.OFFICE_CD,m_office_types.OFFICE_TYPE_CD FROM m_office_hierarchy,m_office_types WHERE SUPERVISOR_OFFICE_CD =officecd
AND m_office_hierarchy.office_cd=m_office_types.office_cd AND m_office_hierarchy.lang_cd=m_office_types.lang_cd AND m_office_hierarchy.RECORD_STATUS <> 'D'
AND m_office_types.RECORD_STATUS <> 'D' AND m_office_types.OFFICE_TYPE_CD=7;
INSERT INTO temp2 
SELECT m_office_hierarchy.OFFICE_CD,m_office_types.OFFICE_TYPE_CD FROM m_office_hierarchy,m_office_types WHERE SUPERVISOR_OFFICE_CD=officecd
AND m_office_hierarchy.office_cd=m_office_types.office_cd AND m_office_hierarchy.lang_cd=m_office_types.lang_cd
AND m_office_hierarchy.RECORD_STATUS <> 'D' AND m_office_types.RECORD_STATUS <> 'D' AND m_office_types.OFFICE_TYPE_CD <> 7 ;
SELECT COUNT(*) INTO table_count FROM temp2;
WHILE (table_count>0)
DO 
INSERT INTO temp1 
SELECT m_office_hierarchy.OFFICE_CD,m_office_types.OFFICE_TYPE_CD FROM m_office_hierarchy,m_office_types WHERE SUPERVISOR_OFFICE_CD IN (SELECT cd FROM temp2)
AND m_office_hierarchy.office_cd=m_office_types.office_cd AND m_office_hierarchy.lang_cd=m_office_types.lang_cd
 AND m_office_hierarchy.RECORD_STATUS <> 'D' AND m_office_types.RECORD_STATUS <> 'D' AND m_office_types.OFFICE_TYPE_CD=7;
INSERT INTO temp3 
SELECT m_office_hierarchy.OFFICE_CD,m_office_types.OFFICE_TYPE_CD FROM m_office_hierarchy,m_office_types WHERE SUPERVISOR_OFFICE_CD IN (SELECT cd FROM temp2)
AND m_office_hierarchy.office_cd=m_office_types.office_cd AND m_office_hierarchy.lang_cd=m_office_types.lang_cd
AND m_office_hierarchy.RECORD_STATUS <> 'D' AND m_office_types.RECORD_STATUS <> 'D' AND m_office_types.OFFICE_TYPE_CD <> 7  AND m_office_hierarchy.OFFICE_CD NOT IN (SELECT cd FROM temp4) AND m_office_hierarchy.OFFICE_CD <> officecd ;
DELETE FROM temp2;
INSERT INTO temp2 SELECT * FROM temp3;
INSERT INTO temp4 SELECT * FROM temp3;
DELETE FROM temp3;
SELECT COUNT(*) INTO table_count FROM temp2;
END WHILE;
SELECT DISTINCT cd,M_OFFICE_TYPES.office_name FROM temp1,m_office_types WHERE temp1.cd=m_office_types.office_cd AND m_office_types.record_status <> 'D';
ELSE
SELECT '' ;
END IF ;
DROP TABLE  temp1;
DROP TABLE  temp2;
DROP TABLE  temp3;
DROP TABLE temp4;
END  $$
DELIMITER ;

--- 迁移的 Oracle 过程 ----------------------------

  create or replace PROCEDURE get_police_statn_for_hierarchy(officecd IN NUMBER,pstsaffcd IN VARCHAR2)
       as
         v_refcur SYS_REFCURSOR;
        table_count  NUMBER(10,0);
        officerInCharge  VARCHAR2(20);
    BEGIN
    -- This procedure was converted on Mon Nov 14 14:57:57 2016 using Ispirer SQLWays 7.0 Build 3434 64bit Licensed to prabhat.gang@gmail.com - prabhat - India (Demo License, Ispirer MnMTK 2015 Mysql to Oracle Database Migration, 1 month, 20161114).

       EXECUTE IMMEDIATE ' TRUNCATE TABLE temp1 ';
       EXECUTE IMMEDIATE ' TRUNCATE TABLE temp2 ';
       EXECUTE IMMEDIATE ' TRUNCATE TABLE temp3 ';

       INSERT INTO temp1
       SELECT m_office_hierarchy.OFFICE_CD,m_office_types.OFFICE_TYPE_CD FROM m_office_hierarchy,m_office_types WHERE SUPERVISOR_OFFICE_CD = officecd
       and m_office_hierarchy.office_cd = m_office_types.office_cd and m_office_hierarchy.lang_cd = m_office_types.lang_cd and m_office_hierarchy.RECORD_STATUS <> 'D'
       and m_office_types.RECORD_STATUS <> 'D' and m_office_types.OFFICE_TYPE_CD = 7;
       INSERT INTO temp2
       SELECT m_office_hierarchy.OFFICE_CD,m_office_types.OFFICE_TYPE_CD FROM m_office_hierarchy,m_office_types WHERE SUPERVISOR_OFFICE_CD = officecd
       and m_office_hierarchy.office_cd = m_office_types.office_cd and m_office_hierarchy.lang_cd = m_office_types.lang_cd
       and m_office_hierarchy.RECORD_STATUS <> 'D' and m_office_types.RECORD_STATUS <> 'D' and m_office_types.OFFICE_TYPE_CD <> 7;
       SELECT COUNT(*) INTO table_count FROM temp2;
       WHILE (table_count > 0) loop
    INSERT INTO temp1
          SELECT m_office_hierarchy.OFFICE_CD,m_office_types.OFFICE_TYPE_CD FROM m_office_hierarchy,m_office_types WHERE SUPERVISOR_OFFICE_CD IN(SELECT cd FROM temp2)
          and m_office_hierarchy.office_cd = m_office_types.office_cd and m_office_hierarchy.lang_cd = m_office_types.lang_cd
          and m_office_hierarchy.RECORD_STATUS <> 'D' and m_office_types.RECORD_STATUS <> 'D' and m_office_types.OFFICE_TYPE_CD = 7;
          INSERT INTO temp3
          SELECT m_office_hierarchy.OFFICE_CD,m_office_types.OFFICE_TYPE_CD FROM m_office_hierarchy,m_office_types WHERE SUPERVISOR_OFFICE_CD IN(SELECT cd FROM temp2)
          and m_office_hierarchy.office_cd = m_office_types.office_cd and m_office_hierarchy.lang_cd = m_office_types.lang_cd
          and m_office_hierarchy.RECORD_STATUS <> 'D' and m_office_types.RECORD_STATUS <> 'D' and m_office_types.OFFICE_TYPE_CD <> 7;
          DELETE FROM temp2;
          INSERT INTO temp2  SELECT * FROM temp3;
          DELETE FROM temp3;
          SELECT COUNT(*) INTO table_count FROM temp2;
          table_count := 100;
       end loop;
       open v_refcur for SELECT DISTINCT cd,M_OFFICE_TYPES.office_name FROM temp1,m_office_types WHERE temp1.cd = m_office_types.office_cd and m_office_types.record_status <> 'D';
       dbms_sql.return_result(v_refcur);

       EXECUTE IMMEDIATE ' TRUNCATE TABLE temp1 ';
       EXECUTE IMMEDIATE ' TRUNCATE TABLE temp2 ';
       EXECUTE IMMEDIATE ' TRUNCATE TABLE temp3 ';

       close v_refcur; 
    END;

完成错误日志同时破坏上述程序:

ORA-29481:无法将隐式结果返回给客户端

ORA-06512:在“SYS.DBMS_SQL”,第 2785 行

ORA-06512:在“SYS.DBMS_SQL”,第 2779 行

ORA-06512:在“CAS_USER.GET_POLICE_STATN_FOR_HIERARCHY”,第 38 行

ORA-06512:在第 8 行

我是 oracle 世界的新手,请帮助我解决上述问题,以便我可以运行上述程序以在 SQL Developer 中查看“v_refcur”SYS_REFCURSOR 输出或结果游标。

【问题讨论】:

为什么需要 SYS_REFCURSOR?你不在你的代码中使用它。你想输出查询SELECT DISTINCT cd,M_OFFICE_TYPES.office_name FROM temp1,m_office_types WHERE temp1.cd = m_office_types.office_cd and m_office_types.record_status &lt;&gt; 'D'的结果吗? temp1temp2temp3 是什么?那些是全局临时表吗?还是那些永久的桌子?在 Oracle 中实现这样的中间结果是非常奇怪的。我希望你真的不需要这些对象。如果您使用的是 12.1,则可以返回隐式结果。但是您还需要 12.1 客户端和一个了解隐式结果集的应用程序,而您似乎没有这些结果集。您可以升级您的客户端,但更常见的是 OUT 类型为 sys_refcursor 的参数 或者,更好的是,拥有一个返回 sys_refcursor 而不是过程的函数。 如果您是“Oracle 世界的新手”,请帮助自己并开始学习PL/SQL Language Reference 以了解基础知识。我不详细了解 MySQL 存储过程,但可以肯定的是,它们与 Oracle 相比有很大不同。在这种特殊情况下,迁移工具编写的代码质量很差(即 “你被解雇了” 类型的质量)甚至无法正常工作。 我读对了吗:WHILE (table_count &gt; 0) loop /* snip */ table_count := 100; end loop; ? 【参考方案1】:

这可能是由于您的客户端驱动程序未更新到 12c。例如。从 Java 调用存储过程时,请确保您拥有最新的 12c JDBC 驱动程序,而不是 11g 驱动程序。

我也有documented this in a separate Q&A,以防这里的问题与 JDBC 无关。

【讨论】:

以上是关于PL/SQL: ORA-29481: 隐式结果不能返回给客户端的主要内容,如果未能解决你的问题,请参考以下文章

oracle游标的使用

PL/SQL 游标的使用详解

Oracle 游标简介

PL/SQL 编程游标存储过程函数

PL/SQL练习游标cursor :oracle 在执行sql语句时,为sql语句所分配的一个私有的内存区域

快速掌握Oracle数据库游标的使用方法有哪些?