子程序参数模式
形参的模式决定了它的行为。
IN | OUT | IN OUT |
默认模式 | 必须指定 | 必须指定 |
给子程序传递值 | 返回值给调用者 | 传递初始值给子程序,返回更新的值给调用者 |
形参行为类似于常量,当子程序开始,它是值就是实参的值或默认值,且子程序不能改变它的值 | 像一个未初始化的变量,当子程序开始值,它的值为NULL,不管的它的实参的值是多少。Oracle建议子程序对它赋值。 | 像一个初始化的变量,子程开始时,它的值为实参的值。Oracle建议子程序更新它的值 |
实参可以是常量、初始化的变量、字面量、表达式 | 实参必须为变量,且它的数据类型不能指定NOT NULL | 实参必须为变量,通常为字符串缓冲区或数字累加器 |
引用传递 | 默认为值传递,如果指定NOCOPY,则可能是引用传递 | 默认为双向值传递,如果指定NOCOPY,则可是能引用传递。 |
技巧:不要对函数的参数使用OUT或IN OUT模式。理想状态是函数有0或多个参数,只返回一个值。带有IN OUT的参数返回多个值,有副作用。
注意:Oracle数据库提供的许多包和类型的下定义使用了下面的符号和声明形参:
i1 IN VARCHAR2 CHARACTER SET ANY_CS i2 IN VARCHAR2 CHARACTER SET i1%CHARSET |
当声明自己的形参和实参的时候,不要使用这种符号,因为这是对于Oacle提供的包类型的实现保留的。
当OUT和IN OUT参数是通过值传递的
n 如果子程序成功退出,则形参的值被赋值给实参。
n 如果子程序因为未处理的异常而结束,则形参的值不赋给实参,实参保留在调用子程序之前的值。
当OUT, IN OUT参数是通过引用传递的,实参和形参引用相同的内存分配,因此如果子程序改变了形参的值,则改变会立即在实参中显现出来。
-- 参数在过程调用之前、之中和之后的值 CREATE OR REPLACE PROCEDURE print (x PLS_INTEGER) IS BEGIN IF x IS NOT NULL THEN DBMS_OUTPUT.PUT_LINE(x); ELSE DBMS_OUTPUT.PUT_LINE('NULL'); END IF; END print; / CREATE OR REPLACE PROCEDURE p ( a PLS_INTEGER, -- 默认为IN b IN PLS_INTEGER, c OUT PLS_INTEGER, d IN OUT BINARY_FLOAT ) IS BEGIN DBMS_OUTPUT.PUT_LINE('在过程P内部:'); DBMS_OUTPUT.PUT('IN a = '); print(a); --1 1 DBMS_OUTPUT.PUT('IN b = '); print(b); --2 20 DBMS_OUTPUT.PUT('OUT c = '); print(c); --NULL NULL DBMS_OUTPUT.PUT_LINE('IN OUT d = ' || TO_CHAR(d)); --4.0E+000 5.0E+000
-- 可以引用IN类型的参数a, b,但不能对它们赋值 c := a + 10; -- 对out参数赋值 d := 10 / b; -- 对in out参数赋值 END; /
DECLARE aa CONSTANT PLS_INTEGER := 1; bb PLS_INTEGER := 2; cc PLS_INTEGER := 3; dd BINARY_FLOAT := 4; ee PLS_INTEGER; ff BINARY_FLOAT := 5; BEGIN DBMS_OUTPUT.PUT_LINE('调用过程P之前:'); DBMS_OUTPUT.PUT('aa = '); print(aa); --1 DBMS_OUTPUT.PUT('bb = '); print(bb); --2 DBMS_OUTPUT.PUT('cc = '); print(cc); --3 DBMS_OUTPUT.PUT_LINE('dd = ' || TO_CHAR(dd)); --4.0E+000
p (aa, -- 常量 bb, -- 初始化变量 cc, -- 初始化变量 dd -- 初始化变量 );
DBMS_OUTPUT.PUT_LINE('在调用P之后:'); DBMS_OUTPUT.PUT('aa = '); print(aa); --1 DBMS_OUTPUT.PUT('bb = '); print(bb); --2 DBMS_OUTPUT.PUT('cc = '); print(cc); --11 DBMS_OUTPUT.PUT_LINE('dd = ' || TO_CHAR(dd)); --5.0E+000
DBMS_OUTPUT.PUT_LINE('在调用P之前:'); DBMS_OUTPUT.PUT('ee = '); print(ee); --NULL DBMS_OUTPUT.PUT_LINE('ff = ' || TO_CHAR(ff)); --5.0E+000
p (1, -- 字面量 (bb + 3) * 4, -- 表达式 ee, -- 未初始变量 ff -- 初始化变量 );
DBMS_OUTPUT.PUT_LINE('调用P之后:'); DBMS_OUTPUT.PUT('ee = '); print(ee); --11 DBMS_OUTPUT.PUT_LINE('ff = ' || TO_CHAR(ff)); --5.0E-001 END; /
|
--因为未处理的异常子程序结束, OUT, IN OUT参数 DECLARE j PLS_INTEGER := 10; k BINARY_FLOAT := 15; BEGIN DBMS_OUTPUT.PUT_LINE('调用P之前:'); DBMS_OUTPUT.PUT('j = '); print(j); DBMS_OUTPUT.PUT_LINE('k = ' || TO_CHAR(k));
p(4, 0, j, k); -- 致使P以ZERO_DIVID异常退出
EXCEPTION WHEN ZERO_DIVIDE THEN DBMS_OUTPUT.PUT_LINE('调用P之后:'); DBMS_OUTPUT.PUT('j = '); print(j); DBMS_OUTPUT.PUT_LINE('k = ' || TO_CHAR(k)); END;
|
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/17013648/viewspace-1131974/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/17013648/viewspace-1131974/