ITPub博客

首页 > 数据库 > Oracle > PLSQL Language Reference-PL/SQL子程序-子程序参数-子程序参数别名

PLSQL Language Reference-PL/SQL子程序-子程序参数-子程序参数别名

原创 Oracle 作者:LuiseDalian 时间:2014-03-29 08:38:08 0 删除 编辑

子程序参数别名

别名就是对相同的内存分配有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);   -- 实参的值可能是3010

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

请登录后发表评论 登录
全部评论

注册时间:2012-02-06

  • 博文量
    1986
  • 访问量
    5568877