参考: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示例
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)。