Oracle PL/SQL进阶编程(第二弹:子程序参数)

子程序可以带有参数,参数可以具有不同的模式,可以按值传递,也可以通过引用传递。

形参与实参

形式参数:子定义子程序时,在定义语句中定义的参数称为形式参数,简称形参。形参的数据类型不包含任何的长度约束。通常使用p开头作为形参的前缀,如p_deptno
实际参数:在调用子程序时,传入的具体参数值称为实际参数,简称实参。实参和它对应的形参必须类型兼容。

参数模式

形参的模式用来控制形参的行为,有3中模式:IN,OUT,IN OUT。如果没有指定,默认为IN。

IN模式的参数称为输入参数,它就像常量一样,不能被赋值。

OUT模式的参数称为输出参数,输出参数将会改变参数的值,因此实参不能用固定字符串或常量来传递,必须是一个变量。
OUT模式的形参会被初始化为NULL,所以形参的数据类型是不能有NOT NULL约束的。

IN OUT模式又称为输入/输出参数,形参可以被读出和写入。他的实参也必须是一个变量,不可以是常量或表达式。如果成功地退出子程序,PL/SQL就会为实参赋值,如果有未捕获的异常发生,PL/SQL就不会为实参赋值。

形参的约束

在子程序定义时,形参不能指定长度的约束,任何指定长度或精度的约束都是不合法的。如:

CREATE OR REPLACE PROCEDURE calcSalary(
    p_job IN VARCHAR2(10),
    p_salary IN OUT NUMBER(10,2))
AS
BEGIN
...
END;

这样是错误的,PL/SQL引擎将抛出编译时错误,必须要去掉对形参中的长度约束。
实际上形参的约束来自于实参,传入的实参具有怎样的长度约束,形参就具有怎样的长度约束。

虽然形参不能用约束声明,但是可以使用%TYPE对其进行约束。如果形参使用了%TYPE进行声明,那么其潜在类型是收到约束的。

参数传递方式

有两种向子程序传递参数的方式:一种是前面见过的按位置传递,另一种是按名称传递。

大多参数传递的场合都是用按位置传递方式,只要传入的实参的位置匹配形参的位置定义即可。如:

calcSalary(v_job,v_sal);

按名称传递是使用=>作为关联的操作符,如:

calcSalary(p_job=>v_job,p_salary=>v_sal);

由于使用了名字进行标识,因此参数的位置就不重要了,这样的写法和上面实际上是一样的:

calcSalary(p_salary=>v_sal,p_job=>v_job);

还可以混合使用按位置传递和按名称传递,但是在这种情况下,位置标识法必须在名称标识法之前。

参数默认值

在定义子程序时,可以使用 DEFAULT关键字或赋值语句为IN模式的参数指定默认值。

CREATE OR REPLACE PROCEDURE newdeptwithdefault (
   p_deptno   dept.deptno%TYPE DEFAULT 57,    --部门编号
   p_dname    dept.dname%TYPE:='管理部',     --部门名称
   p_loc      dept.loc%TYPE DEFAULT '江苏'        --位置
)
AS
BEGIN
    ...
END;

BEGIN
   newdeptwithdefault;       --不指定任何参数,将使用形参默认值
END;

BEGIN
   newdeptwithdefault(58,'事务组');       --p_loc使用默认值
END;

BEGIN
   newdeptwithdefault(p_deptno=>58, p_loc=>'南海');       --p_dname使用默认值
END;

使用NOCOPY编译提示

首先需要理解引用传递和值传递之间的区别。

值传递:当参数通过值传递时,参数将从实际参数中被复制到形式参数中。
引用传递:实际参数的指针被传递到了相应的形式参数中。

默认情况下,PL/SQL通过引用来传递IN参数,引用传递速度快,因为仅实际参数的指针传递到相应的形式参数中,不需要进行复制,这对于占用空间较大的参数,比如集合类型具有较高的效率。而IN OUT参数和OUT参数通过值进行传递,这主要是因为对实际参数的约束可以被校验,当子程序正常结束后,被赋到OUT和IN OUT形参上的值就会复制到对应的实参上。
在使用OUT和IN OUT参数时,如果参数是大型数据结构,比如集合、记录、对象实例,可以使用NOCOPY编译提示按引用进行传递:

parameter_name [mode] NOCOPY datatype

如:

CREATE OR REPLACE PROCEDURE NoCopyDemo
(
    p_InParam IN NUMBER,
    p_InOutParam IN OUT NOCOPY VARCHAR2,
    p_OutParam OUT NOCOPY VARCHAR2
)
IS
...
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章