PL/SQL基础的执行部分
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PL/SQL基础的执行部分相关的知识,希望对你有一定的参考价值。
参考技术A执行部分包含了所有的语句和表达式,执行部分以关键字BEGIN开始,以关键字EXCEPTION结束,如果EXCEPTION不存在,那么将以关键字END结束。分号分隔每一条语句,使用赋值操作符:=或SELECT INTO或FETCH INTO给每个变量赋值,执行部分的错误将在异常处理部分解决,在执行部分中可以使用另一个PL/SQL程序块,这种程序块被称为嵌套块
所有的SQL数据操作语句都可以用于执行部分,PL/SQL块不能再屏幕上显示SELECT语句的输出。SELECT语句必须包括一个INTO子串或者是游标的一部分,执行部分使用的变量和常量必须首先在声明部分声明,执行部分必须至少包括一条可执行语句,NULL是一条合法的可执行语句,事物控制语句COMMIT和ROLLBACK可以在执行部分使用,数据定义语言(Data Definition language)不能在执行部分中使用,DDL语句与EXECUTE IMMEDIATE一起使用或者是DBMS_SQL调用。
执行一个PL/SQL块
SQL*PLUS中匿名的PL/SQL块的执行是在PL/SQL块后输入/来执行,如下面的例子所示:
declare
v_comm_percent constant number:=10;
begin
update emp
set comm=sal*v_comm_percent
where deptno=10;
end
SQL> /
PL/SQL procedure successfully completed.
SQL>
命名的程序与匿名程序的执行不同,执行命名的程序块必须使用execute关键字:
create or replace procedure update_commission
(v_dept in number,v_pervent in number default 10) is
begin
update emp
set comm=sal*v_percent
where deptno=v_dept;
end
SQL>/
Procedure created
SQL>execute update_commission(10,15);
PL/SQL procedure successfully completed.
SQL>
如果在另一个命名程序块或匿名程序块中执行这个程序,那么就不需要EXECUTE关进字。
declare
v_dept number;
begin
select a.deptno
into v_dept
from emp a
where job='PRESIDENT'
update_commission(v_dept);
end
SQL>/
PL/SQL procedure successfully completed
SQL>
控制结构
控制结构控制PL/SQL程序流程的代码行,PL/SQL支持条件控制和循环控制结构。
语法和用途
IF..THEN
语法:
IF condition THEN
Statements 1;
Statements 2;
....
END IF
IF语句判断条件condition是否为TRUE,如果是,则执行THEN后面的语句,如果condition为false或NULL则跳过THEN到END IF之间的语句,执行END IF后面的语句。
IF..THEN...ELSE
语法:
IF condition THEN
Statements 1;
Statements 2;
....
ELSE
Statements 1;
Statements 2;
....
END IF
如果条件condition为TRUE,则执行THEN到ELSE之间的语句,否则执行ELSE到END IF之间的语句。
IF 可以嵌套,可以在IF 或IF ..ELSE语句中使用IF或IF..ELSE语句。
if (a>b) and (a>c) then
g:=a;
else
g:=b;
if c>g then
g:=c;
end if
end if
IF..THEN..ELSIF
语法:
IF condition1 THEN
statement1;
ELSIF condition2 THEN
statement2;
ELSIF condition3 THEN
statement3;
ELSE
statement4;
END IF;
statement5;
如果条件condition1为TRUE则执行statement1,然后执行statement5,否则判断condition2是否为TRUE,若为TRUE则执行statement2,然后执行statement5,对于condition3也是相同的,如果condition1,condition2,condition3都不成立,那么将执行statement4,然后执行statement5。
循环控制
循环控制的基本形式是LOOP语句,LOOP和END LOOP之间的语句将无限次的执行。LOOP语句的语法如下:
LOOP
statements;
END LOOP
LOOP和END LOOP之间的语句无限次的执行显然是不行的,那么在使用LOOP语句时必须使用EXIT语句,强制循环结束,例如:
X:=100;
LOOP
X:=X+10;
IF X>1000 THEN
EXIT;
END IF
END LOOP;
Y:=X;
此时Y的值是1010.
EXIT WHEN语句将结束循环,如果条件为TRUE,则结束循环。
X:=100;
LOOP
X:=X+10;
EXIT WHEN X>1000;
X:=X+10;
END LOOP;
Y:=X;
WHILE..LOOP
WHILE..LOOP有一个条件与循环相联系,如果条件为TRUE,则执行循环体内的语句,如果结果为FALSE,则结束循环。
X:=100;
WHILE X<=1000 LOOP
X:=X+10;
END LOOP;
Y=X;
FOR...LOOP
语法:
FOR counter IN [REVERSE] start_range....end_range LOOP
statements;
END LOOP;
LOOP和WHILE循环的循环次数都是不确定的,FOR循环的循环次数是固定的,counter是一个隐式声明的变量,他的初始值是start_range,第二个值是start_range+1,直到end_range,如果start_range等于end _range,那么循环将执行一次。如果使用了REVERSE关键字,那么范围将是一个降序。
X:=100;
FOR v_counter in 1..10 loop
x:=x+10;
end loop
y:=x;
如果要退出for循环可以使用EXIT语句。
标签
用户可以使用标签使程序获得更好的可读性。程序块或循环都可以被标记。标签的形式是<>。
标记程序块
<>
[DECLARE]
... ... ...
BEGIN
........
[EXCEPTION]
.......
END label_name
标记循环
<>
LOOP
.........
<>
loop
..........
<>
loop
....
EXIT outer_loop WHEN v_condition=0;
end loop innermost_loop;
..........
END LOOP inner_loop;
END LOOP outer_loop;
GOTO语句
语法:
GOTO LABEL;
执行GOTO语句时,控制会立即转到由标签标记的语句。PL/SQL中对GOTO语句有一些限制,对于块、循环、IF语句而言,从外层跳转到内层是非法的。
X :=100;
FOR V_COUNTER IN 1..10 LOOP
IF V_COUNTER =4 THEN
GOTO end_of_loop
END IF
X:=X+10;
<>
NULL
END LOOP
Y:=X;
注意:NULL是一个合法的可执行语句。
嵌套
程序块的内部可以有另一个程序块这种情况称为嵌套。嵌套要注意的是变量,定义在最外部程序块中的变量可以在所有子块中使用,如果在子块中定义了与外部程序块变量相同的变量名,在执行子块时将使用子块中定义的变量。子块中定义的变量不能被父块引用。同样GOTO语句不能由父块跳转道子块中,反之则是合法的。
《OUTER BLOCK》
DECLARE
A_NUMBER INTEGER;
B_NUMBER INTEGER;
BEGIN
--A_NUMBER and B_NUMBER are available here
<>
DECLARE
C_NUMBER INTEGER
B_NUMBER NUMBER(20)
BEGIN
C_NUMBER:=A_NUMBER;
C_NUMBER=OUTER_BLOCK.B_NUMBER;
END SUB_BLOCK;
END OUT_BLOCK;
小结
我们在这篇文章中介绍了PL/SQL的基础语法以及如何使用PL/SQL语言设计和运行PL/SQL程序块,并将PL/SQL程序整合到Oracle服务器中,虽然PL/SQL程序作为功能块嵌入Oracle数据库中,但PL/SQL与ORACLE数据库的紧密结合使得越来越多的Oracle数据库管理员和开发人员开始使用PL/SQL。
oracle数据库之PL/SQL 块结构和组成元素
一、PL/SQL 块
(一)PL/SQL 程序由三个块组成,即声明部分、执行部分、异常处理部分
PL/SQL 块的结构如下:
1、DECLARE
/* 声明部分: 在此声明 PL/SQL 用到的变量,类型及游标,以及局部的存储过程和函数 */
2、BEGIN
/* 执行部分:过程及 SQL 语句 , 即程序的主要部分*
3、EXCEPTION
/* 执行异常部分: 错误处理 */
4、END;
其中 执行部分是必须的。
(二)PL/SQL 块可以分为三类:
1、无名块:动态构造,只能执行一次。
2、子程序:存储在数据库中的存储过程、函数及包等。当在数据库上建立好后可以在其它程序中调用它们。
3、触发器:当数据库发生操作时,会触发一些事件,从而自动执行相应的程序。
二 、PL/SQL 结构
1、PL/SQL 块中可以包含子块;
2、子块可以位于 PL/SQL 中的任何部分;
3、 子块也即 PL/SQL 中的一条命令;
三、 标识符
PL/SQL 程序设计中的标识符定义与 SQL 的标识符定义的要求相同。要求和限制有:
1、标识符名不能超过 30 字符;
2、第一个字符必须为字母;
3、不分大小写;
4、不能用’-‘(减号);
5、不能是 SQL 保留字。
提示: 一般不要把变量名声明与表中字段名完全一样,如果这样可能得到不正确的结果.
例如:下面的例子将会删除所有的纪录,而不是 KING 的记录;
DECLARE Ename varchar2(20) := ’KING’; BEGIN DELETE FROM emp WHERE ename=ename; END;
变量命名在 PL/SQL 中有特别的讲究,建议在系统的设计阶段就要求所有编程人员共同遵守一定的要求,使得整个系统的文档在规范上达到要求。下面是建议的命名方法:
标识符 |
命名规则 |
例子 |
|
|
|
程序变量 |
V_name |
V_name |
|
|
|
程序常量 |
C_Name |
C_company_name |
|
|
|
游标变量 |
Name_cursor |
Emp_cursor |
|
|
|
异常标识 |
E_name |
E_too_many |
|
|
|
表类型 |
Name_table_type |
Emp_record_type |
|
|
|
表 |
Name_table |
Emp |
|
|
|
记录类型 |
Name_record |
Emp_record |
|
|
|
SQL*Plus 替代变量 |
P_name |
P_sal |
|
|
|
绑定变量 |
G_name |
G_year_sal |
|
|
|
四、 PL/SQL 变量类型
在前面的介绍中,有系统的数据类型,也可以自定义数据类型。下表是 ORACLE 类型和 PL/SQL 中的变量类型的合法使用列表:
(一)变量类型
在 ORACLE8i 中可以使用的变量类型有:
1. 字符类型
数据类型 |
长度 |
说明 |
CHAR(n BYTE/CHAR) |
默认1字节,n值最大为2000 |
末尾填充空格以达到指定长度,超过最大长度报错。默认指定长度为字节数,字符长度可以从1字节到四字节。 |
NCHAR(n) |
默认1字符,最大存储内容2000字节 |
末尾填充空格以达到指定长度,n为Unicode字符数。默认为1字节。 |
NVARCHAR2(n) |
最大长度必须指定,最大存储内容4000字节 |
变长类型。n为Unicode字符数 |
VARCHAR2(n BYTE/CHAR) |
最大长度必须指定,至少为1字节或者1字符,n值最大为4000 |
变长类型。超过最大长度报错。默认存储的是长度为0的字符串。 |
VARCHAR |
同VARCHAR2 |
不建议使用 |
2. 数字类型
数据类型 |
长度 |
说明 |
NUMBER(p[,s]) |
1-22字节。 P取值范围1到38 S取值范围-84到127 |
存储定点数,值的绝对值范围为1.0 x 10 -130至1.0 x 10 126。值大于等于1.0 x 10 126时报错。p为有意义的10进制位数,正值s为小数位数,负值s表示四舍五入到小数点左部多少位。 |
BINARY_FLOAT |
5字节,其中有一长度字节。 |
32位单精度浮点数类型。 符号位1位,指数位8位,尾数位23位。 |
BINARY_DOUBLE |
9字节,其中有一长度字节。 |
64位双精度浮点数类型。 |
3. 时间、时间间隔类型
时间字段 |
时间类型有效值 |
时间间隔类型有效值 |
YEAR |
-4712至9999,包括0 |
任何整数 |
MONTH |
01至12 |
0至11 |
DAY |
01至31 |
任何整数 |
HOUR |
00 至 23 |
0 至 23 |
MINUTE |
00 至 59 |
0至 59 |
SECOND |
00 to 59.9(n),9(n)不适用与DATE类型 |
0 to 59.9(n) |
TIMEZONE_HOUR |
-1至14,不适用与DATE和TIMESTAMP类型 |
不可用 |
TIMEZONE_MINUTE |
00至59,不适用与DATE和TIMESTAMP类型 |
不可用 |
TIMEZONE_REGION |
|
不可用 |
TIMEZONE_ABBR |
|
不可用 |
数据类型 |
长度 |
说明 |
DATE |
7字节 |
默认值为SYSDATE的年、月,日为01。包含一个时间字段,若插入值没有时间字段,则默认值为:00:00:00 or 12:00:00 for 24-hour and 12-hour clock time。没有分秒和时间区。 |
TIMESTAMP [(fractional_seconds_precision)] |
7至11字节 |
fractional_seconds_precision为Oracle存储秒值小数部分位数,默认为6,可选值为0到9。没有时间区。 |
TIMESTAMP [(fractional_seconds_precision)] WITH TIME ZONE |
13字节 |
使用UTC,包含字段YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, TIMEZONE_ HOUR, TIMEZONE_MINUTE |
TIMESTAMP [(fractional_seconds_precision)] WITH LOCAL TIME ZONE |
7至11字节 |
存时使用数据库时区,取时使用回话的时区。 |
INTERVAL YEAR [(year_precision)] TO MONTH |
5字节 |
包含年、月的时间间隔类型。year_precision是年字段的数字位数,默认为2,可取0至9。 |
INTERVAL DAY [(day_precision)] TO SECOND [(fractional_seconds_precision)] |
11字节 |
day_precision是月份字段的数字位数,默认为2,可取0至9。 |
1、TO_DATE()、DATE使用的时间字段值都是午夜值。或者使用TRUNC()函数进行过滤,确保时间字段为午夜值。
2、时间和时间间隔类型操作规则:
在DATE和TIMESTAMP(会被转化为DATE类型值)类型上加、减NUMBER类型常量,该常量单位为天数。
所有TIMESTAMP类型运算都以UTC时间为准。即对于TIMESTAMP WITH LOCAL TIME ZONE来说,先转化为UTC时间,计算完成后再转化回来。
3、INTERVAL YEAR TO MONTH常量:
INTERVAL‘year-month’YEAR/MONTH(precision) TO MONTH
year位数超过precision时,返回一个错误。
其中precision为最大的位数,默认为2,可取0到9。
例子:INTERVAL \'123-2\' YEAR(3) TO MONTH 、
INTERVAL \'123\' YEAR(3) 、
INTERVAL \'300\' MONTH(3)。
4、INTERVAL DAY TO SECOND常量:
INTERVAL ‘n/time_expr/n time_expr’ DAY/HOUR/MINUTE(leading_precision) TO HOUR/MINUTE/SECOND(fractional_second_precision)
INTERVAL ‘n/time_expr’ SECOND(leading_precision, fractional_second_precision)
time_expr格式:HH[:MI[:SS[.n]]] or MI[:SS[.n]] or SS[.n] 若n大于分秒精度,则四舍五入n。
只有当第一个字段是DAY时,才可以使用n time_expr。
leading_precision默认为2,可取0至9。
4. 大对象类型
数据类型 |
长度 |
说明 |
BLOB |
最大为(4GB-1)*数据库块大小 |
存储非结构化二进制文件。支持事务处理。 |
CLOB |
最大为(4GB-1)*数据库块大小 |
存储单字节或者多字节字符数据。支持事务处理。 |
NCLOB |
最大为(4GB-1)*数据库块大小 |
存储Unicode数据。支持事务处理。 |
BFILE |
最大为2 32-1字节 |
LOB地址指向文件系统上的一个二进制文件,维护目录和文件名。不参与事务处理。只支持只读操作。 |
5. 其他类型
数据类型 |
长度 |
说明 |
LONG |
最大为2GB |
变长类型,存储字符串。创建表时不要使用该类型。 |
RAW(n) |
最大2000字节,n为字节数,必须指定n |
变长类型,字符集发生变化时不会改变值。 |
LONG RAW |
最大为2GB |
变长类型,不建议使用,建议转化为BLOB类型,字符集发生变化时不会改变值。 |
ROWID |
10字节 |
代表记录的地址。显示为18位的字符串。用于定位数据库中一条记录的一个相对唯一地址值。通常情况下,该值在该行数据插入到数据库表时即被确定且唯一。 |
UROWID(n) |
|
|
(二)复合类型
ORACLE 在 PL/SQL 中除了提供象前面介绍的各种类型外,还提供一种称为复合类型的类型---记录和表.
1、 记录类型
记录类型是把逻辑相关的数据作为一个单元存储起来,称作 PL/SQL RECORD 的域(FIELD),其作用是存放互不相同但逻辑相关的信息。
定义记录类型语法如下:
TYPE record_type IS RECORD( Field1 type1 [NOT NULL] [:= exp1 ], Field2 type2 [NOT NULL] [:= exp2 ], . . . . . . Fieldn typen [NOT NULL] [:= expn ] ) ;
例 1 :
提示:
1) DBMS_OUTPUT.PUT_LINE 过程的功能类似于 Java 中的 System.out.println() 直接将输出结果送到标准输出中.
2) 在使用上述过程之前必须将 SQL * PLUS 的环境参数 SERVEROUTPUT 设置为 ON, 否则将看不到输出结果: set serveroutput on
可以用 SELECT 语句对记录变量进行赋值,只要保证记录字段与查询结果列表中的字段相配即可。
2、使用%TYPE
定义一个变量,其数据类型与已经定义的某个数据变量的类型相同,或者与数据库表的某个列的数据类型相同,这时可以使用%TYPE。
使用%TYPE 特性的优点在于:
1、 所引用的数据库列的数据类型可以不必知道;
2、 所引用的数据库列的数据类型可以实时改变。
例 2:
3、使用%ROWTYPE
PL/SQL 提供%ROWTYPE 操作符, 返回一个记录类型, 其数据类型和数据库表的数据结构相一致。
使用%ROWTYPE 特性的优点在于:
1、 所引用的数据库中列的个数和数据类型可以不必知道
2、 所引用的数据库中列的个数和数据类型可以实时改变
例 3:
五、 运算符和表达式(数据定义)
(一)关系运算符(二)一般运算符
(三)逻辑运算符
六、 变量赋值
在 PL/SQL 编程中,变量赋值是一个值得注意的地方,它的语法如下: variable := expression ;
variable 是一个 PL/SQL 变量, expression 是一个 PL/SQL 表达式.
(一)字符及数字运算特点
空值加数字仍是空值:NULL + < 数字> = NULL
空值加(连接)字符,结果为字符:NULL || <字符串> = < 字符串>
(二)2BOOLEAN 赋值
布尔值只有 TRUE, FALSE 及 NULL 三个值。
(三)数据库赋值
数据库赋值是通过 SELECT语句来完成的,每次执行 SELECT语句就赋值一次,一般要求被赋值的变量与
SELECT中的列名要一一对应。如:
例 9:
DECLARE emp_id emp.empno%TYPE :=7788; emp_name emp.ename%TYPE; wages emp.sal%TYPE; BEGIN SELECT ename, NVL(sal,0) + NVL(comm,0) INTO emp_name, wages FROM emp WHERE empno = emp_id; DBMS_OUTPUT.PUT_LINE(emp_name||’----‘||to_char(wages)); END;
提示:不能将SELECT语句中的列赋值给布尔变量。
(四) 可转换的类型赋值
1、 CHAR 转换为 NUMBER:
使用 TO_NUMBER 函数来完成字符到数字的转换,如:
v_total := TO_NUMBER(‘100.0’) + sal;
2、NUMBER 转换为 CHAR:
使用 TO_CHAR 函数可以实现数字到字符的转换,如:
v_comm := TO_CHAR(‘123.45’) || ’元’ ;
3、字符转换为日期:
使用 TO_DATE 函数可以实现 字符到日期的转换,如:
v_date := TO_DATE(\'2001.07.03\',\'yyyy.mm.dd\');
4、日期转换为字符
使用 TO_CHAR 函数可以实现日期到字符的转换,如:
v_to_day := TO_CHAR(SYSDATE, \'yyyy.mm.dd hh24:mi:ss\') ;
七、 变量作用范围及可见性
在 PL/SQL 编程中,如果在变量的定义上没有做到统一的话,可能会隐藏一些危险的错误,这样的原因主要是变量的作用范围所致。与其它高级语言类似,PL/SQL 的变量作用范围特点是:
1、 变量的作用范围是在你所引用的程序单元(块、子程序、包)内。即从声明变量开始到该块的结束。
2、一个变量(标识)只能在你所引用的块内是可见的。
3、当一个变量超出了作用范围,PL/SQL 引擎就释放用来存放该变量的空间(因为它可能不用了)。
4、在子块中重新定义该变量后,它的作用仅在该块内。
八、 注释
在PL/SQL里,可以使用两种符号来写注释,即:
1、使用双 ‘-‘ ( 减号) 加注释
PL/SQL允许用 – 来写注释,它的作用范围是只能在一行有效。如:
V_Sal NUMBER(12,2); -- 工资变量。
2、使用 /* */ 来加一行或多行注释,如:
/***********************************************/
/* 文件名: department_salary.sql */ /***********************************************/
提示:被解释存放在数据库中的 PL/SQL 程序,一般系统自动将程序头部的注释去掉。只有在 PROCEDURE 之后的注释才被保留;另外程序中的空行也自动被去掉。
九、 简单例子
(一) 简单数据插入例子
例 11:
/* 本例子仅是一个简单的插入,不是实际应用。 */
DECLARE v_ename VARCHAR2(20) := ‘Bill’; v_sal NUMBER(7,2) :=1234.56; v_deptno NUMBER(2) := 10; v_empno NUMBER(4) := 8888; BEGIN INSERT INTO emp ( empno, ename, JOB, sal, deptno , hiredate ) VALUES ( v_empno, v_ename, ‘Manager’, v_sal, v_deptno, TO_DATE(’1954.06.09’,’yyyy.mm.dd’) ); COMMIT; END;
(二) 简单数据删除例子
例 12:
/* 本例子仅是一个简单的删除例子,不是实际应用。 */
DECLARE v_empno number(4) := 8888; BEGIN DELETE FROM emp WHERE empno=v_empno; COMMIT; END;
以上是关于PL/SQL基础的执行部分的主要内容,如果未能解决你的问题,请参考以下文章