【发布时间】:2021-11-01 02:56:36
【问题描述】:
我正在开发一个 PLSQL 包,该包调用另一个 PLSQL 包,该包返回单独的结果(即 OUT 变量),如下所示:
- (1) SYS_REFCURSOR
- (1) 号码
- (1) VARCHAR2
这是我构建的dbfiddle。
链接的dbfiddle的完整代码:
/* Main table - it contains the data to use in a cursor: */ CREATE TABLE tpos_retbenf ( id_serial NUMBER (9,0), serial_nmb NUMBER(12,0) );
/* Destination of the records detected on "tpos_retbenf": */ CREATE TABLE tbl_debug ( msg_text VARCHAR2(1000), record_date DATE );
/* Add values to the main table: */ INSERT INTO tpos_retbenf (id_serial, serial_nmb) VALUES (1, 202108311635);
/* Package that contains the code to execute: */ create or replace PACKAGE PCK_POS_UNO is PROCEDURE SP_POS_UNO (ID_RECORD IN NUMBER, CUR_RET_BENF OUT SYS_REFCURSOR, IDERROR OUT NUMBER, DSERROR OUT VARCHAR2); end PCK_POS_UNO; /
create or replace PACKAGE BODY PCK_POS_UNO is /* This is the procedure that returns results in separated variables: */ PROCEDURE SP_POS_UNO (ID_RECORD IN NUMBER, CUR_RET_BENF OUT SYS_REFCURSOR, IDERROR OUT NUMBER, DSERROR OUT VARCHAR2) AS v_temp number(6) := 0; v_S varchar2(1) := 'S'; BEGIN if ID_RECORD is null or ID_RECORD <= 0 then IDERROR := -1; DSERROR := 'Id no valido para la operacion'; goto finalizar; end if; select count(1) into v_temp from tpos_retbenf r where r.id_serial = ID_RECORD; if v_temp = 0 then IDERROR := -1; DSERROR := 'Id no encontrado'; goto finalizar; end if; OPEN CUR_RET_BENF FOR select r.id_serial, r.serial_nmb from tpos_retbenf r where r.id_serial = ID_RECORD; <<finalizar>> null; END SP_POS_UNO; END PCK_POS_UNO; /
/* Package that calls the "SP_POS_UNO" procedure from the "PCK_POS_UNO" package: */ create or replace PACKAGE PKG_BH_ONLINE_INFORMATION IS PROCEDURE ONLINENOVELTYBEN ( V_NID_DEV IN NUMBER, CV_1 IN OUT SYS_REFCURSOR ); END PKG_BH_ONLINE_INFORMATION; /
create or replace PACKAGE BODY PKG_BH_ONLINE_INFORMATION IS PROCEDURE ONLINENOVELTYBEN ( V_NID_DEV IN NUMBER, CV_1 IN OUT SYS_REFCURSOR ) IS V_USER VARCHAR2(10 CHAR) := 'INTERNET'; V_QUERY VARCHAR2(10000 CHAR); -- Variables: V_OUT_CUR_RET_BENF SYS_REFCURSOR; V_OUT_IDERROR NUMBER; V_OUT_DSERROR VARCHAR2(10000 CHAR); BEGIN /* Here, the "PCK_POS_UNO.SP_POS_UNO" is called from "PKG_BH_ONLINE_INFORMATION" as follows: */ V_QUERY := 'SELECT APPLICATION_POS.PCK_POS_UNO.SP_POS_UNO(:V_NID_DEV, :V_OUT_CUR_RET_BENF, :V_OUT_IDERROR, :V_OUT_DSERROR) FROM DUAL'; EXECUTE IMMEDIATE V_QUERY INTO V_OUT_CUR_RET_BENF, V_OUT_IDERROR, V_OUT_DSERROR USING V_NID_DEV, V_OUT_CUR_RET_BENF, V_OUT_IDERROR, V_OUT_DSERROR ; /* An this error occurs: Error: ORA-00904: "PCK_POS_UNO"."SP_POS_UNO": invalid identifier - StackTrace: ORA-06512: in line 24 */ -- After getting the results in (V_OUT_CUR_RET_BENF, V_OUT_IDERROR, V_OUT_DSERROR) variables, -- a LOOP is executed for retrieve the records in "V_OUT_CUR_RET_BENF" cursor... -- It doesn't continue here due to error shown above. END ONLINENOVELTYBEN; END PKG_BH_ONLINE_INFORMATION; /
当下面的代码要执行时:
V_QUERY := 'SELECT APPLICATION_POS.PCK_POS_UNO.SP_POS_UNO(:V_NID_DEV, :V_OUT_CUR_RET_BENF, :V_OUT_IDERROR, :V_OUT_DSERROR) FROM DUAL';
EXECUTE IMMEDIATE V_QUERY INTO V_OUT_CUR_RET_BENF, V_OUT_IDERROR, V_OUT_DSERROR USING V_NID_DEV, V_OUT_CUR_RET_BENF, V_OUT_IDERROR, V_OUT_DSERROR ;
错误提示:
错误:ORA-00904:“APPLICATION_POS”。“PCK_POS_UNO”。“SP_POS_UNO”:无效标识符 - StackTrace:ORA-06512:在第 24 行
到目前为止我已经尝试过:
- 搜索
ORA-00904错误 - 在 this answer 中说“对查询中涉及的对象的适当权限” - 我分享了这一点,但是,我不知道如何论证这个选项( 因为我可以对那个表做一个简单的SELECT并且结果是显示出来的,因此,他们可能不接受这个论点)。与此论点相关,我无法列出PCK_POS_UNO包“因为 OWNER 与我通常使用的不同(即APPLICATION)”。 - 我复制了这个包/过程,并且能够通过 SQL Developer 执行过程/包 - 查看屏幕截图,但是,同样的错误
ORA-00904发生了。
包的执行截图:
结果:
- 更改调用具有
OUT参数的过程的代码,但是,我无法获得允许编译和执行整个代码的成功组合。
示例 - 全部基于互联网搜索和我自己的“本能”:
(1):在动态sql字符串的末尾添加(;):
V_QUERY := 'SELECT APPLICATION_POS.PCK_POS_UNO.SP_POS_UNO((:V_NID_DEV, :V_OUT_CUR_RET_BENF, :V_OUT_IDERROR, :V_OUT_DSERROR) FROM DUAL;';
(2):删除 OWNER - 在本例中为“APPLICATION_POS”:
V_QUERY := 'SELECT PCK_POS_UNO.SP_POS_UNO(:V_NID_DEV, :V_OUT_CUR_RET_BENF, :V_OUT_IDERROR, :V_OUT_DSERROR) FROM DUAL';
(3):直接调用过程 - 它显示 SP2-0552: bind variable "V_NID_DEV" not declared - 但是,如何?在一个单独的示例中,变量“V_NID_DEV”被声明并具有值“2462013”:
PCK_POS_UNO.SP_POS_UNO(:V_NID_DEV, :V_OUT_CUR_RET_BENF, :V_OUT_IDERROR, :V_OUT_DSERROR);
(4):直接调用过程(同时删除点)-在这种情况下,会生成 ORA-01001 - invalid cursor 错误-我认为这没有意义-因为 OUT 光标没有被打开读取或以某种方式操作。
PCK_POS_UNO.SP_POS_UNO(V_NID_DEV, V_OUT_CUR_RET_BENF, V_OUT_IDERROR, V_OUT_DSERROR);
我真的没有想法了——因为我不熟悉这种类型的创建包和在包之间传递值,而且我没有创建这段代码。
有没有办法让这段代码工作?
【问题讨论】:
-
你不能
select过程从某事中产生结果,因为过程不返回任何东西。所以select proc() from dual不是一个有效的语法。正确的方法是PCK_POS_UNO.SP_POS_UNO(V_NID_DEV, V_OUT_CUR_RET_BENF, V_OUT_IDERROR, V_OUT_DSERROR);,因为你传递的是 PL/SQL 变量,而不是绑定变量。 4 呢:很难说,什么是错的,因为它按预期工作。检查更正db<>fiddle -
另外请提供 minimal 可重现的例子。重新键入所有那些不使用其输入参数的长标识符和嵌套过程非常无聊。
-
@astentx,代码就是这样(甚至不是我的),正在处理遗留代码,tbh。
-
但无论如何,关于特定的重点问题。如果您已经花费了足够的时间进行调试以定位有问题的代码和平,并且可以重现该问题,那么在这种情况下,周围的代码将只有几行。如果您从头开始构建代码,那么您肯定会面临代码不再工作的步骤。在这个特定的情况下,它几乎是在最开始的时候(简单的过程,为
select * from dual打开了光标,带有一个输入和输出参数)。 -
@astentx,虽然我创建了一个 minimal 可重现的示例 - 相信我,这是我可以管理的最紧凑的示例。老实说,我感谢您的帮助。如果您想发布答案,我会接受。
标签: oracle plsql plsql-package