一、PL/SQL块的词法
PL/SQL中可以使用字母、数字、空格和特殊符号等,主要包括:
标识符——变量、关键字、保留字
分隔符——分号,逗号,加号或减号等
常量——字符串,数字,布尔型变量
注释——单行注释、多行注释
编写PL/SQL程序时,需要注意以下两点:
1. 字符和日期必须使用单引号引用,单引号中间可以引用双引号。
2. 数字可以是单独的数字,也可以使科学计数法。
为了养成良好的编程,最好使用tab键对代码进行缩进,有关键字的行回车另起一行,以使程序更加易读,逻辑结构更加清晰。
二、注释
PL/SQL和其他编程语言一样,也经常需要用到注释。注释部分程序执行时会自动忽略。它的注释主要有两种:
1. 单行注释:使用-- 表示,注释的范围仅限于-- 所在的行;
2. 多行注释:使用/* */表示,注释的范围是/* */所包含的所有行。
如下面这个例子,就同时用到了单行注释和多行注释:
SQL> edit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
DECLARE
v_annual_sal NUMBER (9,2);
monthly_sal NUMBER;
BEGIN
/*
Compute the annual salary based on themonthly salary
input from the user
*/
-- 使用了多行注释
monthly_sal := 3000;
v_annual_sal := monthly_sal * 12;
-- The following line displays theannual salary
-- 使用了单行注释
DBMS_OUTPUT.PUT_LINE(v_annual_sal);
END;
/
SQL> /
1
2
36000
PL/SQL procedure successfullycompleted.
三、SQL函数在PL/SQL中的应用
PL/SQL和SQL是无缝衔接的,因此SQL的很多函数可以在PL/SQL中直接引用,比如SQL中的单行函数可以直接使用;但是一些GROUP函数和DECODE函数则无法在PL/SQL中使用。不过PL/SQL有自己的条件控制语句,可以做更为灵活的操作。
下面举几个SQL函数在PL/SQL中使用的例子:
SQL> edit
1
2
3
4
5
6
7
8
9
DECLARE
v_desc_size INTEGER(5);
v_prod_description VARCHAR2(70) := 'Youcan use this product with your radios for higher frequency';
BEGIN
v_desc_size :=LENGTH(v_prod_description);
-- 这里使用了SQL的函数LENGTH()
DBMS_OUTPUT.PUT_LINE(v_desc_size);
END;
/
SQL> /
1
2
62
PL/SQL procedure successfully completed.
需要注意的是,Oracle11g之前,PL/SQL中使用递增函数(Sequences)的方法是:
1
2
3
4
5
6
DECLARE
v_new_id NUMBER;
BEGIN
SELECT my_seq.NEXTVAL INTO v_new_idFROM Dual;
-- 需要写成完整的形式
END;
但是在Oracle11g之后,递增函数简化成如下的形式:
1
2
3
4
5
6
DECLARE
v_new_id NUMBER;
BEGIN
v_new_id := my_seq.NEXTVAL;
-- 可以写成简化的形式了
END;
四、数据类型的转换
PL/SQL中要进行转换的数据必须是相似的,比如数字123和字符串’123’是可以互相转换的,但是’abc’则不能转换为数字。
PL/SQL中数据类型的转换主要分两类:
1. 隐式转换——隐式转换是指数据会自动转换。但是需要注意的是,自动转换受制于NLS环境变量,如果环境变量没有进行相应的配置,则有可能无法转换,因此不推荐这种方式。
下面看一个数据类型转换的例子:
SQL> edit
1
2
3
4
5
6
7
8
9
10
11
DECLARE
a_number NUMBER;
BEGIN
a_number := '125';
-- '125'是个字符串
a_number := a_number + 3;
--'125'自动转换成了数字
DBMS_OUTPUT.PUT_LINE(to_char(a_number,'9999'));
-- 使用了to_char这个函数进行显示转换
END;
/
SQL> @notes/s1.sql
1
2
128
PL/SQLprocedure successfully completed.
2. 显式转换——使用专用的函数来转换。如TO_CHAR,TO_DATE, TO_NUMBER, TO_TIMESTAMP等函数。
如要进行日期转换:
SQL> edit
1
2
3
4
5
6
7
8
DECLARE
v_date_of_joining DATE;
BEGIN
v_date_of_joining := TO_DATE('February02,2000','Month DD, YYYY');
-- 使用TO_DATE这个函数进行显式转换
DBMS_OUTPUT.PUT_LINE(v_date_of_joining);
END;
/
SQL> /
1
2
02-FEB-00
PL/SQLprocedure successfully completed.
五、块的嵌套
A. 嵌套块可以放的位置:
PL/SQL可以嵌套其他的块,被嵌套的块可以放在以下两个部分:
1. 可执行部分,即BEGIN处;
2. 异常处理部分,即EXCEPTION部分。
需要注意的是,嵌套块最多不要超过3层。
B. 变量的范围(SCOPE):
内层嵌套块可以引用外层块中声明的变量;
但是外层块不可以引用内层块中声明的变量。
下面来看一个变量引用范围的例子:
SQL> edit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
DECLARE
v_outer_variable VARCHAR2(20) :='GLOBAL _VARIABLE';
-- 声明在外层块中的变量
BEGIN
DECLARE
v_inner_variable VARCHAR2(20):= 'LOCAL VARIABLE';
-- 声明在内层块中的变量
BEGIN
DBMS_OUTPUT.PUT_LINE(v_inner_variable);
-- 内层块中的函数可以引用内层块声明的变量
DBMS_OUTPUT.PUT_LINE(v_outer_variable);
-- 内层块的函数也可以引用外层块声明的变量
END;
DBMS_OUTPUT.PUT_LINE(v_outer_variable);
-- 外层块只能引用声明在外层块的变量
END;
SQL> /
1
2
3
4
LOCALVARIABLE
GLOBAL_VARIABLE
GLOBAL_VARIABLE
PL/SQLprocedure successfully completed.
如果修改一下,在外层块里引用一下内层块的变量:
SQL> edit
1
2
3
4
5
6
7
8
9
10
11
12
13
DECLARE
v_outer_variable VARCHAR2(20) :='GLOBAL _VARIABLE';
BEGIN
DECLARE
v_inner_variable VARCHAR2(20):= 'LOCAL VARIABLE';
BEGIN
DBMS_OUTPUT.PUT_LINE(v_inner_variable);
DBMS_OUTPUT.PUT_LINE(v_outer_variable);
END;
DBMS_OUTPUT.PUT_LINE(v_outer_variable);
DBMS_OUTPUT.PUT_LINE(v_inner_variable);
END;
/
SQL> /
1
2
3
4
5
6
7
8
DBMS_OUTPUT.PUT_LINE(v_inner_variable);
*
ERRORat line 11:
ORA-06550:line 11, column 23:
PLS-00201:identifier 'V_INNER_VARIABLE' must be declared
ORA-06550:line 11, column 2:
PL/SQL:Statement ignored
-- 报错了,说明无法引用内层块声明的变量
C.变量的可见性(visibility)
如果声明变量时出现了重名的情况,则采用就近原则,优先采用本地的变量,而在外层块中的变量会被覆盖(invisibility)。
下面来看一个变量名重名的例子:
SQL> edit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
--Example about variable scope and visibility in nest blocks
DECLARE
v_father_name VARCHAR2(20) :='Patrick';
v_date_of_birth DATE := '20-Apr-1972';
-- 定义了父亲的名字和生日
BEGIN
DECLARE
v_child_name VARCHAR2(20) :='Mike';
v_date_of_birth DATE :='12-Dec-2002';
-- 定义了儿子的名字和生日
BEGIN
DBMS_OUTPUT.PUT_LINE('Father''sName: ' || v_father_name);
DBMS_OUTPUT.PUT_LINE('Date ofBirth: ' || v_date_of_birth);
-- 这里引用了父亲的名字
--但是根据就近原则,引用了儿子的生日
DBMS_OUTPUT.PUT_LINE('Child''sName: ' || v_child_name);
-- 引用了儿子的名字
END;
DBMS_OUTPUT.PUT_LINE('Date of Birth: '|| v_date_of_birth);
-- 内层块执行结束后内存被释放,此时引用的是父亲的生日
END;
/
SQL> /
1
2
3
4
5
6
7
Father'sName: Patrick
Dateof Birth: 12-DEC-02
-- 父亲的名字,儿子的生日
Child'sName: Mike
Dateof Birth: 20-APR-72
--儿子的名字,父亲的生日
PL/SQLprocedure successfully completed.
D.使用限定词标签引用变量
如果要内层块一定要引用外层块的变量,在声明时使用标签,引用时指定标签作为修饰语,则可以避免变量覆盖的情况。
看下面这组例子:
SQL> edit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
BEGIN<>
--使用了标签<>
DECLARE
v_father_name VARCHAR2(20) :='Patrick';
v_date_of_birth DATE := '20-Apr-1972';
BEGIN
DECLARE
v_child_name VARCHAR2(20) :='Mike';
v_date_of_birth DATE :='12-Dec-2002';
BEGIN
DBMS_OUTPUT.PUT_LINE('Father''sName: ' || v_father_name);
DBMS_OUTPUT.PUT_LINE('Date ofBirth: ' || outer.v_date_of_birth);
-- 引用变量时指明该变量是外层块中的变量。
DBMS_OUTPUT.PUT_LINE('Child''sName: ' || v_child_name);
DBMS_OUTPUT.PUT_LINE('Date ofBirth: ' || v_date_of_birth);
-- 这里引用的变量是内层块的变量
END;
END;
END outer;
SQL> /
1
2
3
4
5
6
Father'sName: Patrick
Dateof Birth: 20-APR-72
Child'sName: Mike
Dateof Birth: 12-DEC-02
--这一次父亲的名字和生日、孩子的名字和生日能够匹配了
PL/SQLprocedure successfully completed.
当然,也可以同时使用outer和inner标签
SQL> edit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
BEGIN<>
-- 使用outer标签
DECLARE
v_father_name VARCHAR2(20) :='Patrick';
v_date_of_birth DATE := '20-Apr-1972';
BEGIN<>
-- 使用inner标签
DECLARE
v_child_name VARCHAR2(20) :='Mike';
v_date_of_birth DATE :='12-Dec-2002';
BEGIN
DBMS_OUTPUT.PUT_LINE('Father''sName: ' || v_father_name);
DBMS_OUTPUT.PUT_LINE('Date ofBirth: ' || outer.v_date_of_birth);
-- 引用时指明是outer的变量
DBMS_OUTPUT.PUT_LINE('Child''sName: ' || v_child_name);
DBMS_OUTPUT.PUT_LINE('Date ofBirth: ' || inner.v_date_of_birth);
-- 引用时指明是inner的变量
END;
END;
ENDouter;
/
SQL> /
1
2
3
4
5
6
Father'sName: Patrick
Dateof Birth: 20-APR-72
Child'sName: Mike
Dateof Birth: 12-DEC-02
-- 和上一次的执行结果是一致的
PL/SQLprocedure successfully completed.
限定词除了可以明确指定外,还可以使用包名、Procedure的名字。使用限定词来引用变量,是一个很好的编程习惯,可以防止混淆和冲突。
阅读(2285) | 评论(0) | 转发(0) |