PL/SQL是ORACLE对标准数据库语言的扩展,ORACLE公司已经将PL/SQL整合到ORACLE 服务器和其他工具中了,近几年中更多的开发人员和DBA开始使用PL/SQL,本文将讲述PL/SQL基础语法,结构和组件、以及如何设计并执行一个 PL/SQL程序。
PL/SQL的优点
从版本6开始PL/SQL就被可靠的整合到ORACLE中了,一旦掌握PL/SQL的优点以及其独有的数据管理的便利性,那么你很难想象ORACLE缺了PL/SQL的情形。PL/SQL 不是一个独立的产品,他是一个整合到ORACLE服务器和ORACLE工具中的技术,可以把PL/SQL看作ORACLE服务器内的一个引擎,sql语句执行者处理单个的sql语句,PL/SQL引擎处理PL/SQL程序块。当PL/SQL程序块在PL/SQL引擎处理时,ORACLE服务器中的SQL语句执行器处理pl/sql程序块中的SQL语句。
PL/SQL的优点如下:
. PL/SQL是一种高性能的基于事务处理的语言,能运行在任何ORACLE环境中,支持所有数据处理命令。通过使用PL/SQL程序单元处理SQL的数据定义和数据控制元素。
. PL/SQL支持所有SQL数据类型和所有SQL函数,同时支持所有ORACLE对象类型
. PL/SQL块可以被命名和存储在ORACLE服务器中,同时也能被其他的PL/SQL程序或SQL命令调用,任何客户/服务器工具都能访问PL/SQL程序,具有很好的可重用性。
. 可以使用ORACLE数据工具管理存储在服务器中的PL/SQL程序的安全性。可以授权或撤销数据库其他用户访问PL/SQL程序的能力。
. PL/SQL代码可以使用任何ASCII文本编辑器编写,所以对任何ORACLE能够运行的操作系统都是非常便利的
. 对于SQL,ORACLE必须在同一时间处理每一条SQL语句,在网络环境下这就意味作每一个独立的调用都必须被oracle服务器处理,这就占用大量的服务器时间,同时导致网络拥挤。而PL/SQL是以整个语句块发给服务器,这就降低了网络拥挤。
PL/SQL块结构
PL/SQL是一种块结构的语言,组成PL/SQL程序的单元是逻辑块,一个PL/SQL 程序包含了一个或多个逻辑块,每个块都可以划分为三个部分。与其他语言相同,变量在使用之前必须声明,PL/SQL提供了独立的专门用于处理异常的部分,下面描述了PL/SQL块的不同部分:
声明部分(Declaration section)
声明部分包含了变量和常量的数据类型和初始值。这个部分是由关键字DECLARE开始,如果不需要声明变量或常量,那么可以忽略这一部分;需要说明的是游标的声明也在这一部分。
执行部分(Executable section)
执行部分是PL/SQL块中的指令部分,由关键字BEGIN开始,所有的可执行语句都放在这一部分,其他的PL/SQL块也可以放在这一部分。
异常处理部分(Exception section)
这一部分是可选的,在这一部分中处理异常或错误,对异常处理的详细讨论我们在后面进行。
PL/SQL块语法
[DECLARE] ---declaration statements BEGIN ---executable statements [EXCEPTION] ---exception statements END |
FUNCTION name [{parameter[,parameter,...])] RETURN datatypes IS [local declarations] BEGIN execute statements [EXCEPTION exception handlers] END [name] |
PROCEDURE name [(parameter[,parameter,...])] IS [local declarations] BEGIN execute statements [EXCEPTION exception handlers ] END [name] |
Variable_name [CONSTANT] databyte [NOT NULL][:=|DEFAULT expression] |
ZERO_VALUE CONSTANT NUMBER:=0; |
Datatype | Range | Subtypes | description |
BINARY_INTEGER | -214748-2147483647 | NATURAL NATURAL NPOSITIVE POSITIVEN SIGNTYPE |
用于存储单字节整数。 要求存储长度低于NUMBER值。 用于限制范围的子类型(SUBTYPE): NATURAL:用于非负数 POSITIVE:只用于正数 NATURALN:只用于非负数和非NULL值 POSITIVEN:只用于正数,不能用于NULL值 SIGNTYPE:只有值:-1、0或1. |
NUMBER | 1.0E-130-9.99E125 | DEC DECIMAL DOUBLE PRECISION FLOAT INTEGERIC INT NUMERIC REAL SMALLINT |
存储数字值,包括整数和浮点数。可以选择精度和刻度方式,语法: number[( <precision></precision> [,<scale></scale>])]。 缺省的精度是38,scale是0. |
PLS_INTEGER | -2147483647-2147483647 | 与BINARY_INTEGER基本相同,但采用机器运算时,PLS_INTEGER提供更好的性能 。 |
datatype | rang | subtype | description |
CHAR | 最大长度32767字节 | CHARACTER | 存储定长字符串,如果长度没有确定,缺省是1 |
LONG | 最大长度2147483647字节 | 存储可变长度字符串 | |
RAW | 最大长度32767字节 | 用于存储二进制数据和字节字符串,当在两个数据库之间进行传递时,RAW数据不在字符集之间进行转换。 | |
LONGRAW | 最大长度2147483647 | 与LONG数据类型相似,同样他也不能在字符集之间进行转换。 | |
ROWID | 18个字节 | 与数据库ROWID伪列类型相同,能够存储一个行标示符,可以将行标示符看作数据库中每一行的唯一键值。 | |
VARCHAR2 | 最大长度32767字节 | STRINGVARCHAR | 与VARCHAR数据类型相似,存储可变长度的字符串。声明方法与VARCHAR相同 |
datatype | range | description |
BOOLEAN | TRUE/FALSE | 存储逻辑值TRUE或FALSE,无参数 |
DATE | 01/01/4712 BC | 存储固定长的日期和时间值,日期值中包含时间 |
operator | operation |
+ | 加 |
- | 减 |
/ | 除 |
* | 乘 |
** | 乘方 |
operator | operation |
< | 小于操作符 |
<= | 小于或等于操作符 |
> | 大于操作符 |
>= | 大于或等于操作符 |
= | 等于操作符 |
!= | 不等于操作符 |
<> | 不等于操作符 |
:= | 赋值操作符 |
operator | operation |
IS NULL | 如果操作数为NULL返回TRUE |
LIKE | 比较字符串值 |
BETWEEN | 验证值是否在范围之内 |
IN | 验证操作数在设定的一系列值中 |
operator | operation |
AND | 两个条件都必须满足 |
OR | 只要满足两个条件中的一个 |
NOT | 取反 |
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> |
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> |
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> |
IF condition THEN Statements 1; Statements 2; .... END IF |
IF condition THEN Statements 1; Statements 2; .... ELSE Statements 1; Statements 2; .... END IF |
if (a>b) and (a>c) then g:=a; else g:=b; if c>g then g:=c; end if end if |
IF condition1 THEN statement1; ELSIF condition2 THEN statement2; ELSIF condition3 THEN statement3; ELSE statement4; END IF; statement5; |
X:=100; LOOP X:=X+10; IF X>1000 THEN EXIT; END IF END LOOP; Y:=X; |
X:=100; LOOP X:=X+10; EXIT WHEN X>1000; X:=X+10; END LOOP; Y:=X; |
X:=100; WHILE X<=1000 LOOP X:=X+10; END LOOP; Y=X; |
FOR counter IN [REVERSE] start_range....end_range LOOP statements; END LOOP; |
X:=100; FOR v_counter in 1..10 loop x:=x+10; end loop y:=x; |
<<label_name></label_name>> [DECLARE] ... ... ... BEGIN ........ [EXCEPTION] ....... END label_name |
<<outer_name></outer_name>> LOOP ......... <<inner_loop></inner_loop>> loop .......... <<innermost_loop></innermost_loop>> loop .... EXIT outer_loop WHEN v_condition=0; end loop innermost_loop; .......... END LOOP inner_loop; END LOOP outer_loop; |
X :=100; FOR V_COUNTER IN 1..10 LOOP IF V_COUNTER =4 THEN GOTO end_of_loop END IF X:=X+10; <<end_of_loop></end_of_loop>> NULL END LOOP Y:=X; |
《OUTER BLOCK》 DECLARE A_NUMBER INTEGER; B_NUMBER INTEGER; BEGIN --A_NUMBER and B_NUMBER are available here <<sub_block></sub_block>> 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; |