plsql下nocopy引數的含義

regonly1發表於2010-03-13

對於nocopy引數,瞭解的時間也不是很長。一般我們在寫函式或過程的時候,使用out的情況比較少,更不提效率上覺察到差別了。
後來瞭解到指定nocopy時,效率要比不指定的要高。但是不知道為什麼。
今天看到了一篇Oracle最佳化文件,看出了一些端倪。
當遇到異常時,plsql在這層之上增加了一些處理,以確保過程或函式的行為是正確的。如:
當外部指定的out引數已經有一個值,在呼叫函式時出現了異常,此時plsql將返回該引數原來的值,而不是在函式處理過程中的某個值。
以上是沒有指定nocopy的情況,當指定了該引數時,plsql將不會增加這些處理,因此外部指定的out引數將是函式執行過程中的某個值。
實驗:
(20111026更新)
有nocopy的情況:

SQL> declare
  2      v_num number := 0;
  3      procedure gets(p_val out nocopy number)as
  4      begin
  5          p_val := 3.1415;
  6          raise_application_error(-20001, 'aa');
  7      end gets;
  8  begin
  9      begin
 10          gets(v_num);
 11      exception when others then
 12          dbms_output.put_line(v_num);
 13      end;
 14  end;
 15  /
 
3.1415
 
PL/SQL procedure successfully completed

無nocopy的情況:

SQL> declare
  2      v_num number := 0;
  3      procedure gets(p_val out /*nocopy */number)as
  4      begin
  5          p_val := 3.1415;
  6          raise_application_error(-20001, 'aa');
  7      end gets;
  8  begin
  9      begin
 10          gets(v_num);
 11      exception when others then
 12          dbms_output.put_line(v_num);
 13      end;
 14  end;
 15  /
 
0
 
PL/SQL procedure successfully completed

紅色部分是兩者的差異,其他都一樣,其結果就是nocopy的作用。通常在物件、集合、記錄型別的引數傳遞時會有明顯效果(效果顯著視copy的資料量而定)。

################################
增加一個過程:prc(ret in out varchar2);
create or replace procedure prc(
    ret in out pls_integer) as
begin
    ret := 2;
    raise_application_error(-20001, 'out test!');
end prc;

用以下匿名過程進行測試:
declare
    vv pls_integer := 1;
    excep exception;
    pragma exception_init(excep, -20001);
begin
    prc(vv);
exception when excep then
    dbms_output.put_line(vv);
end;
觀察當ret in out 指定了nocopy引數和沒指定時的輸出值:
SQL> set serveroutput on
SQL>
SQL> create or replace procedure prc(
  2      ret in out pls_integer) as
  3  begin
  4      ret := 2;
  5      raise_application_error(-20001, 'out test!');
  6  end prc;
  7  /
 
Procedure created
 
SQL>
SQL> declare
  2      vv pls_integer := 1;
  3      excep exception;
  4      pragma exception_init(excep, -20001);
  5  begin
  6      prc(vv);
  7  exception when excep then
  8      dbms_output.put_line(vv);
  9  end;
 10  /
 
1
 
PL/SQL procedure successfully completed
發現此時的輸出值是1,即保留了原來的值。
使用nocopy引數:
SQL>
SQL> create or replace procedure prc(
  2      ret in out nocopy pls_integer) as
  3  begin
  4      ret := 2;
  5      raise_application_error(-20001, 'out test!');
  6  end prc;
  7  /
 
Procedure created
 
SQL>
SQL> declare
  2      vv pls_integer := 1;
  3      excep exception;
  4      pragma exception_init(excep, -20001);
  5  begin
  6      prc(vv);
  7  exception when excep then
  8      dbms_output.put_line(vv);
  9  end;
 10  /
 
2
 
PL/SQL procedure successfully completed
此時變為2,即過程中的那個值。nocopy使plsql在執行過程中不再對out引數值做特殊的管理,使得總體的效能得到了提高。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12932950/viewspace-629399/,如需轉載,請註明出處,否則將追究法律責任。

相關文章