Oracle nvl2 在存储过程 PLS-00201 中不起作用:必须声明标识符 'NVL2'
Oracle nvl2 not working in stored procedure PLS-00201: identifier 'NVL2' must be declared
如题,我正在写一些Oracle上的存储过程,首先我检查了版本
SELECT * FROM v$version;
结果
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
PL/SQL Release 11.2.0.4.0 - Production
CORE 11.2.0.4.0 Production
TNS for Linux: Version 11.2.0.4.0 - Production
NLSRTL Version 11.2.0.4.0 - Production
...
并且,使用常规 SQL 查询尝试了 NVL2
select 'Test: ' || nvl2('...', 'things', 'nothing') from dual;
select 'Test: ' || nvl2('', 'things', 'nothing') from dual;
结果似乎是对的
Test: things
Test: nothing
...
所以我确认11g确实支持NLV2功能,我现在可以开始编写我的存储过程,如下所示:
create or replace procedure my_schema.SP_READ_MEMBER(noP in varchar2, nameP in varchar2, idNoP in varchar2, birthdayP in varchar2, resultP out sys_refcursor)
is
v_prg_name varchar2(20) := 'SP_READ_MEMBER';
sys_sql varchar2(1000);
begin
Insertlog(SYSDATE, v_prg_name, '1.0 Start');
sys_sql := sys_sql || 'select a.no, a.name, a.id_no, to_char(a.birthday, ''yyyy/MM/dd'') as birthday, ''REGISTERED'' as type, email, mobile from rep where 1=1 ';
sys_sql := sys_sql || nvl2(noP,'and no='''|| noP ||'''', ''); --PLS-00201
open resultP for sys_sql;
Insertlog(SYSDATE, v_prg_name, '2.0 Finished w/o error');
exception
when others then
declare
error_time VARCHAR2(30) := RTRIM(TO_CHAR(SYSDATE, 'YYYY/MM/DD, HH24:MI:SS'));
error_code NUMBER := SQLCODE;
error_msg VARCHAR2(300) := SQLERRM;
begin
rollback;
DBMS_OUTPUT.PUT_LINE(error_time || ',' || TO_CHAR(error_code) || ',' || error_msg);
Insertlog(SYSDATE, v_prg_name, error_msg || ', 3.0 ERROR, sql:' || sys_sql);
end;
end;
/
Oracle 告诉我它编译错误,这是
PLS-00201: 必须声明标识符 'NVL2'
为什么函数在常规查询中有效,但在存储过程中却未声明?
NVL2
在 SQL 中有效,但在 PL/SQL 中无效,除非您使用的是 21c 或更高版本。
并非每个 SQL 关键字也适用于 PL/SQL,这很愚蠢,但以前发生过几次。 Oracle 一直在逐步统一 SQL 和 PL/SQL,他们最终可能会使用此功能。目前,我认为这个问题已包含在 My Oracle Support 文档 Note 359506.1 Pls-00201 Assigning The Result of NVL2() To A Variable In a PLSQL Block
中。虽然该文档不可用,但即使是具有支持访问权限的人也无法使用。
目前,我建议使用不同的语法。就个人而言,我发现 CASE
版本更清晰,即使它有点冗长。
变化:
sys_sql := sys_sql || nvl2(noP,'and no='''|| noP ||'''', '');
收件人:
sys_sql := sys_sql || case when nop is not null then 'and no='''|| noP ||'''' else '' end;
NVL2 适用于 SQL 但不适用于 PL/SQL。
变化:
sys_sql := sys_sql || nvl2(noP,'and no='''|| noP ||'''', '');
收件人:
select sys_sql || nvl2(noP,'and no='''|| noP ||'''', '') into sys_sql from dual;
如题,我正在写一些Oracle上的存储过程,首先我检查了版本
SELECT * FROM v$version;
结果
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
PL/SQL Release 11.2.0.4.0 - Production
CORE 11.2.0.4.0 Production
TNS for Linux: Version 11.2.0.4.0 - Production
NLSRTL Version 11.2.0.4.0 - Production
...
并且,使用常规 SQL 查询尝试了 NVL2
select 'Test: ' || nvl2('...', 'things', 'nothing') from dual;
select 'Test: ' || nvl2('', 'things', 'nothing') from dual;
结果似乎是对的
Test: things
Test: nothing
...
所以我确认11g确实支持NLV2功能,我现在可以开始编写我的存储过程,如下所示:
create or replace procedure my_schema.SP_READ_MEMBER(noP in varchar2, nameP in varchar2, idNoP in varchar2, birthdayP in varchar2, resultP out sys_refcursor)
is
v_prg_name varchar2(20) := 'SP_READ_MEMBER';
sys_sql varchar2(1000);
begin
Insertlog(SYSDATE, v_prg_name, '1.0 Start');
sys_sql := sys_sql || 'select a.no, a.name, a.id_no, to_char(a.birthday, ''yyyy/MM/dd'') as birthday, ''REGISTERED'' as type, email, mobile from rep where 1=1 ';
sys_sql := sys_sql || nvl2(noP,'and no='''|| noP ||'''', ''); --PLS-00201
open resultP for sys_sql;
Insertlog(SYSDATE, v_prg_name, '2.0 Finished w/o error');
exception
when others then
declare
error_time VARCHAR2(30) := RTRIM(TO_CHAR(SYSDATE, 'YYYY/MM/DD, HH24:MI:SS'));
error_code NUMBER := SQLCODE;
error_msg VARCHAR2(300) := SQLERRM;
begin
rollback;
DBMS_OUTPUT.PUT_LINE(error_time || ',' || TO_CHAR(error_code) || ',' || error_msg);
Insertlog(SYSDATE, v_prg_name, error_msg || ', 3.0 ERROR, sql:' || sys_sql);
end;
end;
/
Oracle 告诉我它编译错误,这是
PLS-00201: 必须声明标识符 'NVL2'
为什么函数在常规查询中有效,但在存储过程中却未声明?
NVL2
在 SQL 中有效,但在 PL/SQL 中无效,除非您使用的是 21c 或更高版本。
并非每个 SQL 关键字也适用于 PL/SQL,这很愚蠢,但以前发生过几次。 Oracle 一直在逐步统一 SQL 和 PL/SQL,他们最终可能会使用此功能。目前,我认为这个问题已包含在 My Oracle Support 文档 Note 359506.1 Pls-00201 Assigning The Result of NVL2() To A Variable In a PLSQL Block
中。虽然该文档不可用,但即使是具有支持访问权限的人也无法使用。
目前,我建议使用不同的语法。就个人而言,我发现 CASE
版本更清晰,即使它有点冗长。
变化:
sys_sql := sys_sql || nvl2(noP,'and no='''|| noP ||'''', '');
收件人:
sys_sql := sys_sql || case when nop is not null then 'and no='''|| noP ||'''' else '' end;
NVL2 适用于 SQL 但不适用于 PL/SQL。
变化:
sys_sql := sys_sql || nvl2(noP,'and no='''|| noP ||'''', '');
收件人:
select sys_sql || nvl2(noP,'and no='''|| noP ||'''', '') into sys_sql from dual;