簡體   English   中英

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中無效。

並非每個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;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM