使用 EXECUTE IMMEDIATE 调用程序包内部过程时出现 ORA-00904 错误
Error ORA-00904 while calling procedure inside package using EXECUTE IMMEDIATE
我正在开发一个 PLSQL 包,它调用另一个 PLSQL 包,returns 分离结果(即 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 ;
错误说:
Error: ORA-00904: "APPLICATION_POS"."PCK_POS_UNO"."SP_POS_UNO": invalid identifier -
StackTrace: ORA-06512: in line 24
到目前为止我已经尝试过:
- 搜索
ORA-00904
错误 - 在 this answer 中说“对查询中涉及的对象的适当权限 ” - 我分享了,但是,我不知道不知道如何论证这个选项(因为我可以对 table 做一个简单的 SELECT
并且结果是 shwon,因此,他们可能不接受这个论点).与此论点相关,我无法列出 PCK_POS_UNO
包“因为 OWNER 与我通常使用的包不同(即 APPLICATION
)”。
- 我复制了这个 package/procedure 并且能够通过 SQL 开发人员执行 procedure/package - 查看屏幕截图,但是,发生相同的错误
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);
我真的 运行 没有想法 - 因为我不熟悉这种创建包和在包之间传递值的类型,而且我没有创建此代码。
有什么方法可以使这段代码起作用吗?
包修改为调用过程SP_POS_UNO:
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:='Begin
PCK_POS_UNO.SP_POS_UNO(:V_NID_DEV, :V_OUT_CUR_RET_BENF, :V_OUT_IDERROR, :V_OUT_DSERROR);
End;';
--
EXECUTE IMMEDIATE V_QUERY
USING V_NID_DEV,
out V_OUT_CUR_RET_BENF,
out V_OUT_IDERROR,
out V_OUT_DSERROR ;
Dbms_Output.Put_Line('V_OUT_IDERROR='||V_OUT_IDERROR);
Dbms_Output.Put_Line('V_OUT_DSERROR='||V_OUT_DSERROR);
--
CV_1:=V_OUT_CUR_RET_BENF;
END ONLINENOVELTYBEN;
--
END PKG_BH_ONLINE_INFORMATION;
我正在开发一个 PLSQL 包,它调用另一个 PLSQL 包,returns 分离结果(即 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 ;
错误说:
Error: ORA-00904: "APPLICATION_POS"."PCK_POS_UNO"."SP_POS_UNO": invalid identifier - StackTrace: ORA-06512: in line 24
到目前为止我已经尝试过:
- 搜索
ORA-00904
错误 - 在 this answer 中说“对查询中涉及的对象的适当权限 ” - 我分享了,但是,我不知道不知道如何论证这个选项(因为我可以对 table 做一个简单的SELECT
并且结果是 shwon,因此,他们可能不接受这个论点).与此论点相关,我无法列出PCK_POS_UNO
包“因为 OWNER 与我通常使用的包不同(即APPLICATION
)”。 - 我复制了这个 package/procedure 并且能够通过 SQL 开发人员执行 procedure/package - 查看屏幕截图,但是,发生相同的错误
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);
我真的 运行 没有想法 - 因为我不熟悉这种创建包和在包之间传递值的类型,而且我没有创建此代码。
有什么方法可以使这段代码起作用吗?
包修改为调用过程SP_POS_UNO:
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:='Begin
PCK_POS_UNO.SP_POS_UNO(:V_NID_DEV, :V_OUT_CUR_RET_BENF, :V_OUT_IDERROR, :V_OUT_DSERROR);
End;';
--
EXECUTE IMMEDIATE V_QUERY
USING V_NID_DEV,
out V_OUT_CUR_RET_BENF,
out V_OUT_IDERROR,
out V_OUT_DSERROR ;
Dbms_Output.Put_Line('V_OUT_IDERROR='||V_OUT_IDERROR);
Dbms_Output.Put_Line('V_OUT_DSERROR='||V_OUT_DSERROR);
--
CV_1:=V_OUT_CUR_RET_BENF;
END ONLINENOVELTYBEN;
--
END PKG_BH_ONLINE_INFORMATION;