IN OUT NOCOPY 分析

来源:互联网 发布:一个程序员的基本技术 编辑:程序博客网 时间:2024/05/29 19:56

当我们声明一个参数是IN类型时,进行传参是将传给该参数一个实参的指针;

当我们声明一个参数是OUT或者IN OUT类型时,进行传参是将传给该参数一个实参的拷贝;

只有当程序正常结束时,赋给OUT或者IN OUT类型参数的值才会返回(除非使用了NOCOPY)。

将NOCOPY应用在传递数据量很大的参数(such as collections, records, and instances of object types)时,可起到优化性能的作用。

当参数是OUT或者IN OUT类型时:没有NOCOPY=按值传递(ByVal);加上NOCOPY=按引用传递(ByRef)。


pl/sql中对out,in out参数使用的?默认形参会复制一份实参的副本,然后在内部传递,修改等,发生异常,不会赋值给实参,控制权交还调用环境,

而实参值不变,还是调用前的值。而使用了nocopy后,形参将获得一个指向实参的指针,然后在内部传递,赋值都直接修改实参了,此时如果异常发生,

控制权交还调用环境,但是实参已经被修改了。无法还原成调用前的值。


PS:如果没有NOCOPY ,如果函数中间报错退出,NOCOPY参数还是原来的值,

    如果有NOCOPY,中间出错后,如果有对NOCOPY参数进行操作,返回的将是操作后的值,无法返回原来传进来的值。


例如:

DECLARE  l_1 NUMBER := 10;  l_2 NUMBER := 20;  l_3 NUMBER := 30;  PROCEDURE test_out(p1 IN NUMBER, x1 IN 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(-20001, 'test NOCOPY');  END;BEGIN    dbms_output.put_line('before, l_1=' || l_1 || ', l_2=' || l_2 || ', l_3=' || l_3);  BEGIN    --the OUT parameter has no value at all until the program terminates successfully,    --unless you have requested use of the NOCOPY hint    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=30inside test_out, x1=10inside test_out, x2=10SQLCODE => -20001, SQLERRM => ORA-20001: test NOCOPYafter, l_1=10, l_2=20, l_3=10




原创粉丝点击