子程序参数别名
别名就是对相同的内存分配有2个不同的名称。子程序参数别名化通常发生在编译器以引用方式方式传递实参,也发生在子程序有光标变量参数。
(1)通过引用传递的子程序参数别名使用
当编译器通过引用传递实参的时候,实参和形参引用相同的内存分配。因此如果子程序修改了形参的值,则改变会立即在实参中呈献出来。
编译器通常对IN参数采用引用传递,但结果的别名使用不会引起问题,因为子程序不能对IN参数赋值。
如果对OUT, IN OUT参数指定了NOCOPY,则参数以引用方式传递。NOCOPY只是一个指示,子程序每次调用时,编译器决定是遵守还是忽略NOCOPY。因此别名使用可以对一次调用发生,不会对其它的发生,从而使子程序的结果不确定:
n 如果实参是全局变量,则对形参的赋值,可能在全局变量中体现出来。
n 如果相同的变量对于2个形参是实参,则对任何一个形参的赋值,可能立即在2个形参中体现出来。
n 如果实参是一个包变量,则对形参或包变量的赋值,可能会在形参和包变量中立即体现出来。
n 如果子程序异常退出,则对形参的赋值可能在实参中体现出来。
--全局变量作为实参的别名使用 --如果编译器遵守NOCOPY(引用传递),则结果为aardvark --如果不遵守NOCOPY(值传递,结果为aardwolf DECLARE TYPE Definition IS RECORD ( word VARCHAR2(20), meaning VARCHAR2(200) );
TYPE Dictionary IS VARRAY(2000) OF Definition; lexicon Dictionary := Dictionary(); -- 全局变量
PROCEDURE add_entry ( word_list IN OUT Dictionary -- NOCOPY形参 ) IS BEGIN word_list(1).word := 'aardvark'; END;
BEGIN lexicon.EXTEND; lexicon(1).word := 'aardwolf'; add_entry(lexicon); -- 全局变量为实参 DBMS_OUTPUT.PUT_LINE(lexicon(1).word); END;
|
DECLARE n NUMBER := 10; PROCEDURE p ( n1 IN NUMBER, n2 IN OUT NUMBER, n3 IN OUT NOCOPY NUMBER ) IS BEGIN n2 := 20; -- 过程成功调用之后,实参的值为20 DBMS_OUTPUT.put_line(n1); -- 实参的值仍然是10 n3 := 30; -- 可能立即改变实参的值 DBMS_OUTPUT.put_line(n1); -- 实参的值可能是30或10 END;
BEGIN p(n, n, n); DBMS_OUTPUT.put_line(n); END; / 10 30 20 |
(3)光标变量参数子程序别名使用
光标变量参数是指针,因此如果子程序将一个光标变量参数赋值给另一个,则它们指向相同的内存单元,这种别名使用可能会有不期望的结果。
-- 光标变量子程序参数别名使用 DECLARE TYPE EmpCurTyp IS REF CURSOR; c1 EmpCurTyp; c2 EmpCurTyp;
PROCEDURE get_emp_data ( emp_cv1 IN OUT EmpCurTyp, emp_cv2 IN OUT EmpCurTyp) IS emp_rec employees%ROWTYPE; BEGIN OPEN emp_cv1 FOR SELECT * FROM employees; emp_cv2 := emp_cv1; -- 现在2个变量指向相同的内存单元 FETCH emp_cv1 INTO emp_rec; -- 获取第1行 FETCH emp_cv1 INTO emp_rec; -- 获取第2行 FETCH emp_cv2 INTO emp_rec; -- 获取第3行 CLOSE emp_cv1; -- 会关闭2个光标变量 FETCH emp_cv2 INTO emp_rec; -- 因为已经关闭,所以再获取数据会引发异常 END; BEGIN get_emp_data(c1, c2); END; /
|
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/17013648/viewspace-1131975/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/17013648/viewspace-1131975/