plsql下nocopy参数的含义

对于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/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/12932950/viewspace-629399/

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值