Oracle NOCOPY使用

参考:http://blog.csdn.net/IndexMan/article/details/17092821

      PLSQL运行引擎在存储过程和函数之间传参有2种方法:传值和传引用

      默认情况,OUT和IN OUT参数通过传值方式传递,IN参数是传引用方式。程序执行前IN OUT参数的实际值将被复制给形参。程序执行中间,临时变量保存参数的输出值。如果程序正常退出,这些值将被复制回原参数。如果程序异常退出,那么原参数值将不会改变。当OUT和IN OUT参数为大数据结构,诸如:集合、记录、对象类型实例时,通过传值方式的COPY动作将会导致程序执行速度下降,使用内存量上升。尤其是该程序被多次调用时更是如此。

      为避免此类情况,我们可以指定NOCOPY暗示,告诉PLSQL编译器通过传引用方式传递OUT 和IN OUT参数。这样,形参将不会COPY参数实际值,也就是说形参和ACTUAL VALUE指向同一内存地址(memory location)。以此提高程序执行性能。

1、使用nocopy示例

      本例仅仅是为了说明nocopy的使用原理,一般只有在参数为大数据结构(如:集合、record和Object)时才会用nocopy,对于基本类型的引用传递带来性能上的好处可以忽略不计。
DECLARE
  l_1 NUMBER := 10;
  l_2 NUMBER := 20;
  l_3 NUMBER := 30;
  PROCEDURE test_out(p1 IN NUMBER,
                     x1 OUT NUMBER,
                     x2 IN OUT NOCOPY NUMBER) IS
  BEGIN
    x1 := p1;
    dbms_output.put_line('inside test_out, x1=' || x1);
    x2 := p1;
    dbms_output.put_line('inside test_out, x2=' || x2);
    raise_application_error(-20005, 'test NOCOPY');
  END;
BEGIN
  dbms_output.put_line('before, l_1=' || l_1 || ', l_2=' || l_2 ||
                       ', l_3=' || l_3);
  BEGIN 
    test_out(l_1, l_2, l_3);
  EXCEPTION
    WHEN OTHERS THEN
      dbms_output.put_line('SQLCODE => ' || SQLCODE || ', SQLERRM => ' ||
                           SQLERRM);
  END;
  dbms_output.put_line('after, l_1=' || l_1 || ', l_2=' || l_2 || ', l_3=' || l_3);
END;

      输出结果:

before, l_1=10, l_2=20, l_3=30
inside test_out, x1=10
inside test_out, x2=10
SQLCODE => -20005, SQLERRM => ORA-20005: test NOCOPY
after, l_1=10, l_2=20, l_3=10
        本例中x1是值传递的,所以虽然程序异常,实参1_2的值没有改变,仍然是10。x2是引用传递的,形参和实参引用的地址是一个,因为形参x2先改变后发生异常,所以虽然发生异常,实参指向的地址的值已经改变了,即20。

2、nocopy限制

1、如果实参为整个关联数组则该限制不起作用。
2、实参被强制指定精度,比例或not null时,该限制将不适用按最大长度强制的字符串参数。
3、实参和形参都是记录类型,二者存在以隐式方式或使用了%ROWTYPE类型声明时,作用在对应字段的强制说明不一制。
4、传递实参需要隐式类型转换时。
5、子程序涉及到远程调用(RPC---database link or as an external procedure)。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值