As title, I'm writing some Stored Procedure on Oracle, first I checked the version
SELECT * FROM v$version;
with result
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
...
And, tried NVL2 with regular SQL query
select 'Test: ' || nvl2('...', 'things', 'nothing') from dual;
select 'Test: ' || nvl2('', 'things', 'nothing') from dual;
result seems right
Test: things
Test: nothing
...
So I confirmed 11g did support NLV2 function, I can now begin to write my stored procedure, like following :
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 told me it compiled with error, which is
PLS-00201: identifier 'NVL2' must be declared
How come a function works in regular query, but become undeclared in Stored Procedure ?
The NVL2 function can be used in the following versions of Oracle/PLSQL: Oracle 12c, Oracle 11g, Oracle 10g, Oracle 9i, Oracle 8i.
What is the difference between nvl and nvl2? Answer: The nvl function only has two parameters while the nvl parameter has three arguments. The nvl2 like like combining an nvl with a decode because you can transform a value: NVL ( expr1 , expr2 ): If expr1 is null, then NVL returns expr2.
NVL2 lets you determine the value returned by a query based on whether a specified expression is null or not null. If expr1 is not null, then NVL2 returns expr2 . If expr1 is null, then NVL2 returns expr3 .
Nvl(arg1,arg2) nvl is used for converting null values. In nvl if argument 1 is null then it returns argument 2 but argument 1 is not null it returns itself. In nvl2 (arg1,arg2,arg3) in nvl2 it converts any number into according to given number with null also .
NVL2
works in SQL but not PL/SQL unless you are on version 21c or higher.
Not every SQL keyword also works in PL/SQL, which is silly, but it's happened a few times before. Oracle has been gradually unifying SQL and PL/SQL, and chances are they'll get to this function eventually. For now, I think this issue is covered by the My Oracle Support document Note 359506.1 Pls-00201 Assigning The Result of NVL2() To A Variable In a PLSQL Block
. Although that document is not available, even to people with a support access.
For now, I recommend using a different syntax. Personally, I find the CASE
version to be clearer, even if it is a bit wordier.
Change:
sys_sql := sys_sql || nvl2(noP,'and no='''|| noP ||'''', '');
To:
sys_sql := sys_sql || case when nop is not null then 'and no='''|| noP ||'''' else '' end;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With