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 <> 'D'
的结果吗?
temp1
、temp2
和 temp3
是什么?那些是全局临时表吗?还是那些永久的桌子?在 Oracle 中实现这样的中间结果是非常奇怪的。我希望你真的不需要这些对象。如果您使用的是 12.1,则可以返回隐式结果。但是您还需要 12.1 客户端和一个了解隐式结果集的应用程序,而您似乎没有这些结果集。您可以升级您的客户端,但更常见的是 OUT
类型为 sys_refcursor
的参数
或者,更好的是,拥有一个返回 sys_refcursor
而不是过程的函数。
如果您是“Oracle 世界的新手”,请帮助自己并开始学习PL/SQL Language Reference 以了解基础知识。我不详细了解 MySQL 存储过程,但可以肯定的是,它们与 Oracle 相比有很大不同。在这种特殊情况下,迁移工具编写的代码质量很差(即 “你被解雇了” 类型的质量)甚至无法正常工作。
我读对了吗:WHILE (table_count > 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: 隐式结果不能返回给客户端的主要内容,如果未能解决你的问题,请参考以下文章