#参数
在PL/SQL里,参数可区分为形参和实参两个概念。
形参:在定义PL/SQL对象时指定的参数,位于头部结构里PL/SQL对象名后面的括号中。
实参:在调用PL/SQL对象时指定的参数,位于调用时指定的PL/SQL对象名后面的括号中。
PL/SQL执行器将把实参与形参按照如下三种方式之一进行一一对应:
- 按位置对应。
- 指定名称的方式对应。
- 前两种方式混合,但是在有多个形参的时候,如果有一个形参对应的实参是按名称指定,则其后的形参对应的实参都要使用按名称方式指定。
如果实参的数据类型与形参不一致,系统会对其进行到形参数据类型的转换,转换规则参考CAST函数描述,如转换失败将抛出错误。
Note:
与CAST中将
CHAR
默认为CHAR(1)
不同,在PL/SQL中的参数转换无此规则。
示例
--此处的argu称为形参
CREATE OR REPLACE PROCEDURE ya_proc(argu1 FLOAT, argu2 VARCHAR DEFAULT 'shenzhen') AS
BEGIN
DBMS_OUTPUT.PUT_LINE(TO_CHAR(argu1)||'------'||argu2);
END;
/
--此处的argu称为实参,该值将被赋给形参
SET NUMWIDTH 20;
exec ya_proc('4');
--result
4.0E+000------shenzhen
--无法将实参转换到对应的形参数据类型时,抛出错误
exec ya_proc('shenzhen');
--result
YAS-00008 type convert error : not a valid number
# 形参的格式
形参的格式为:参数名称 [参数类型] [NOCOPY] 数据类型 [缺省值]。
其中,数据类型里不应该包含长度、精度等属性。
# 形参的类型
包括IN、OUT和IN OUT三种类型。在定义PL/SQL对象时,可以为每一个形参显式地指定一个类型,或者不指定而使用默认的IN类型。
# IN参数
IN参数用于向过程体传递一个值,过程体不能修改该参数的值。此时对应的实参可以为常量或变量。
# OUT参数
OUT参数用于向调用器返回一个值。此时对应的实参必须为变量,且实参的值不会被赋给形参,而是过程体执行完成后,将形参值赋给实参用于返回。
# IN OUT参数
IN OUT参数向过程体传递一个初始值,并向调用器返回一个更新后的值。此时对应的实参必须为变量,且实参的值赋给形参,在过程体内部可读可写;过程体执行结束后,将形参值赋给实参用于返回。
# NOCOPY
对于OUT和IN OUT参数类型,可同时指定NOCOPY关键字,该关键字用于语法兼容,无实际含义。
# 形参的缺省值
只能为IN参数指定缺省值,且缺省值需符合该形参的数据类型要求。
对于指定了缺省值的形参,其对应实参可省略,前提是所有指定了缺省值的形参应该定义在括号最后面位置,且应该同时都指定或者都省略,否则不能保证实参对应到正确的形参。但在实参使用"=>"传入参数值时,无需此前提要求。
示例
--创建含三种类型形参的存储过程
CREATE OR REPLACE PROCEDURE ya_proc(
argu_a INT,
argu_b IN INT,
argu_c OUT INT,
argu_d IN OUT BINARY_FLOAT
) IS
BEGIN
DBMS_OUTPUT.PUT_LINE('Inside procedure ya_proc:');
DBMS_OUTPUT.PUT('IN argu_a = ');
DBMS_OUTPUT.PUT_LINE(NVL(TO_CHAR(argu_a), 'NULL'));
DBMS_OUTPUT.PUT('IN argu_b = ');
DBMS_OUTPUT.PUT_LINE(NVL(TO_CHAR(argu_b), 'NULL'));
DBMS_OUTPUT.PUT('OUT argu_c = ');
DBMS_OUTPUT.PUT_LINE(NVL(TO_CHAR(argu_c), 'NULL'));
DBMS_OUTPUT.PUT_LINE('IN OUT argu_d = ' || TO_CHAR(argu_d));
argu_c := argu_a+10;
argu_d := 10/argu_b;
END;
/
--创建匿名块调用ya_proc,展示三种类型形参在执行存储过程前、中、后时的值
DECLARE
aa INT := 1;
bb INT := 2;
cc INT := 3;
dd BINARY_FLOAT := 4;
ee INT;
ff BINARY_FLOAT := 5;
BEGIN
DBMS_OUTPUT.PUT_LINE('Before invoking procedure ya_proc:');
DBMS_OUTPUT.PUT('aa = ');
DBMS_OUTPUT.PUT_LINE(NVL(TO_CHAR(aa), 'NULL'));
DBMS_OUTPUT.PUT('bb = ');
DBMS_OUTPUT.PUT_LINE(NVL(TO_CHAR(bb), 'NULL'));
DBMS_OUTPUT.PUT('cc = ');
DBMS_OUTPUT.PUT_LINE(NVL(TO_CHAR(cc), 'NULL'));
DBMS_OUTPUT.PUT_LINE('dd = ' || TO_CHAR(dd));
ya_proc (aa,
bb,
cc,
dd
);
DBMS_OUTPUT.PUT_LINE('After invoking procedure ya_proc:');
DBMS_OUTPUT.PUT('aa = ');
DBMS_OUTPUT.PUT_LINE(NVL(TO_CHAR(aa), 'NULL'));
DBMS_OUTPUT.PUT('bb = ');
DBMS_OUTPUT.PUT_LINE(NVL(TO_CHAR(bb), 'NULL'));
DBMS_OUTPUT.PUT('cc = ');
DBMS_OUTPUT.PUT_LINE(NVL(TO_CHAR(cc), 'NULL'));
DBMS_OUTPUT.PUT_LINE('dd = ' || TO_CHAR(dd));
DBMS_OUTPUT.PUT_LINE('Before invoking procedure ya_proc:');
DBMS_OUTPUT.PUT('ee = ');
DBMS_OUTPUT.PUT_LINE(NVL(TO_CHAR(ee), 'NULL'));
DBMS_OUTPUT.PUT_LINE('ff = ' || TO_CHAR(ff));
ya_proc (1,
(bb+3)*4,
ee,
ff
);
DBMS_OUTPUT.PUT_LINE('After invoking procedure ya_proc:');
DBMS_OUTPUT.PUT('ee = ');
DBMS_OUTPUT.PUT_LINE(NVL(TO_CHAR(ee), 'NULL'));
DBMS_OUTPUT.PUT_LINE('ff = ' || TO_CHAR(ff));
END;
/
--result
Before invoking procedure ya_proc:
aa = 1
bb = 2
cc = 3
dd = 4.0E+000
Inside procedure ya_proc:
IN argu_a = 1
IN argu_b = 2
OUT argu_c = NULL
IN OUT argu_d = 4.0E+000
After invoking procedure ya_proc:
aa = 1
bb = 2
cc = 11
dd = 5.0E+000
Before invoking procedure ya_proc:
ee = NULL
ff = 5.0E+000
Inside procedure ya_proc:
IN argu_a = 1
IN argu_b = 20
OUT argu_c = NULL
IN OUT argu_d = 5.0E+000
After invoking procedure ya_proc:
ee = 11
ff = 5.0E-001