标记主程序体结束部分
declare
说明部分 (变量说明,例外说明 〕
begin
语句序列 (DML语句〕…
exception
例外处理语句
End;
■ PL/SQL字符集
PL/SQL语言有效字符包括以下三类
所有大写和小写英文字母
0~9的阿拉伯数字
操作符,包括(、)、+、-、*、/、<、>、!、=、@、%等
PL/SQL标识符
标识符的最大长度为30个字符,不区分大小写,但建议在标识符中适当使用大小写,以增加程序的可读性。
■ PL/SQL常量和变量
在PL/SQL程序运行时,需要定义一些变量来存放一些数据。
常量和变量在使用前必须声明,可以使用DECLARE对变量进行声明,语法如下:
DECLARE
<变量名> <变量类型>:=默认值;
….
在DECLARE块中可以同时声明多个常量和变量。声明普通常量或变量是需要说明以下信息:
常量或变量的名称
常量或变量的数据类型
■ 声明常量
声明常量的基本格式如下:
<常量名> constant <数据类型> := <值>;
:= 为赋值语句
关键字constant表示声明的是常量。常量一旦定义,在以后的使用中其值不再改变。
一些固定的大小为了防止有人改变,最好定义成常量。
例如
Pass_Score constant INTEGER := 60 ;
■ 声明变量
声明变量的基本格式如下:
<变量名> <数据类型>[(宽度) := <初始值>];
变量声明是没有关键字,但要指定数据类型,宽度和初始值可以定义也可以不定义。
例如
Address VARCHAR2(30) := ‘地址未知’;
PL/SQL对一个未初始化的变量,将被默认赋值为NULL
例如
Address VARCHAR2(30);
例如
SET SERVEROUTPUT ON;
DECLARE
Pass_Score constant INTEGER:=60;
Address VARCHAR2(30):='北京海淀区';
BEGIN
DBMS_OUTPUT.PUT_LINE(Pass_Score);
DBMS_OUTPUT.PUT_LINE(Address);
END;
使用SET SERVEROUTPUT ON命令设置环境变量SERVEROUTPUT为打开状态,从而使PL/SQL程序能够在SQL*Plus中输出结果
使用函数DBMS_OUTPUT.PUT_LINE()可以输出参数的值
■ 数据类型
%TYPE数据类型
当定义PL/SQL变量存放值时,必须确保变量使用合适的数据类型和长度,否则可能会在运行过程中出现PL/SQL运行错误
为了避免这种不必要的错误,可以使用%TYPE属性来定义变量
当使用%TYPE属性定义变量时,Oracle会自动地按照数据库表列或其他变量来确定新变量的类型和长度
%ROWTYPE数据类型
如果一张表中包含较多的列,则可以使用%ROWTYPE来定义一个表示表中一行记录的变量
declare
v_ename emp.ename%type;
v_deptno dept.deptno%type;
v_dept_row dept%rowtype;
begin
select ename ,deptno into v_ename,v_deptno
from emp where empno=&eno;
select * into v_dept_row from dept where deptno=v_deptno;
dbms_output.put_line('您要查找的员工是:'||v_ename
||',所在部门信息为:');
dbms_output.put_line('部门编号:'||v_deptno||
' 部门名称:'||v_dept_row.dname||' 所在地:'||v_dept_row.loc);
end;
%record数据类型
declare
type emp_record_type is RECORD((--定义一个记录类型,包含员工信息
ename emp.ename%type,
sal emp.sal%type,
comm emp.comm%type,
total_sal sal%type);
v_emp_record emp_record_type;--声明记录类型变量
begin
select ename,sal,nvl(comm,0),sal+nvl(comm,0) into v_emp_record
from emp where empno=7369;
dbms_output.put_line('员工姓名:'|| v_emp_record.ename);
dbms_output.put_line('基本工资:'|| v_emp_record.sal);
dbms_output.put_line('奖金:'|| v_emp_record.comm);
dbms_output.put_line('实发工资:'|| v_emp_record.total_sal);
TABLE数据类型
declare
type dept_table_type is table of dept%rowtype
index by binary_integer;
v_dept_table dept_table_type;
begin
select * into v_dept_table(0) from dept where deptno=10;
select * into v_dept_table(1) from dept where deptno=20;
dbms_output.PUT_LINE('编号:'||v_dept_table(0).deptno||' 名称:'
||v_dept_table(0).dname||' 所在地:'||v_dept_table(0).loc);
dbms_output.PUT_LINE('编号:'||v_dept_table(1).deptno||' 名称:'
||v_dept_table(1).dname||' 所在地:'||v_dept_table(1).loc);
end;
接收用户的输入赋值
用into关键字可以将查询结果的值,设置给变量:
set serveroutput on
declare
id number(4);
nm varchar(30);
begin
select empno,ename into id,nm from emp where empno=7369;
dbms_output.put_line('编号'||id||'名称'||nm);
--以下是异常处理 -–可选
exception
when NO_DATA_FOUND then
dbms_output.put_line('没有你要查询的数据');
when others then
dbms_output.put_line('其他错误');
end;
流程控制语句是所有过程性程序语言的关键
PL/SQL的主要控制语句如下:
if...then elsif … then end if;
判断if正确则执行then,否则执行else(elsif为嵌套判断)
注意elsif,里面少一下e.
Case var when … then when … then end
有逻辑的从数值中做出选择
Loop exit end loop
循环控制,用判断语句执行exit
Loop exit when … end loop
同上,当when为真时执行exit
while..loop end loop
for...in...loop end loop
已知循环次数的循环
IF语句
IF 条件表达式1 THEN
语句段1
ELSIF 条件表达式2 THEN
语句段2
ELSIF 条件表达式3 THEN
语句段3
......
ELSIF 条件表达式n
语句段n
END IF;
CASE语句
CASE
WHEN 条件表达式1 THEN
语句段1;
WHEN 条件表达式2 THEN
语句段2;
......
ELSE
语句段n;
END CASE;
循环语句LOOP..EXIT..END
此语句的功能是重复执行循环体中的程序块,直到执行EXIT语句,则退出循环。
LOOP...EXIT...END语句的语法结构如下
LOOP
<程序块 1>
IF <条件表达式> THEN
EXIT
END IF
<程序块 2>
END LOOP;
EXIT WHEN (结束语句)
重新实现1~4累加
SET ServerOutPut ON;
DECLARE
varNum INTEGER := 1;
varSum INTEGER := 0;
BEGIN
LOOP
varSum := varSum + varNum;
dbms_output.put_line(varNum);
EXIT WHEN varNum = 4;
dbms_output.put_line('+');
varNum := varNum + 1;
END LOOP;
dbms_output.put_line('=');
dbms_output.put_line(varSum);
END
再次实现1~4累加
DECLARE
varNum INTEGER := 1;
varSum INTEGER := 0;
BEGIN
WHILE varNum <= 4 LOOP
varSum := varSum + varNum;
dbms_output.put_line(varNum);
IF varNum < 4 THEN
dbms_output.put_line('+');
END IF;
varNum := varNum + 1;
END LOOP;
dbms_output.put_line('=');
dbms_output.put_line(varSum);
END
再次实现1~4累加
DECLARE
varNum INTEGER := 1;
varSum INTEGER := 0;
BEGIN
FOR varNum IN 1..4 LOOP
varSum := varSum + varNum;
dbms_output.put_line(varNum);
IF varNum < 4 THEN
dbms_output.put_line('+');
END IF;
END LOOP;
dbms_output.put_line('=');
dbms_output.put_line(varSum);
END;
FOR 循环变量 in [REVERSE] 初值表达式..终值表达式 LOOP
语句段;
END LOOP;
■ 异常处理
PL/SQL程序在运行过程中,可能会出现错误或异常现象
例如:无法建立到Oracle的连接或用0做除数。好的程序应该对可能发生的异常情况进行处理,异常处理代码在EXCEPTION块中实现
可以使用WHEN语句来定义异常。WHEN语句的使用方法如下:
EXCEPTION
WHEN <异常情况名> THEN
<异常处理代码>
WHEN <异常情况名> THEN
<异常处理代码>
...
WHEN OTHERS THEN
<异常处理代码>
预定义异常
针对一些常见的错误,PL/SQL预定义了一些异常错误
当PL/SQL程序违反了Oracle的规定或超出了系统规定的限制时,就会隐含地引发一个预定义的错误
预定义异常种类(红色的重点)
异常 |
说明 |
ACCESS_INTO_NULL |
在未初始化对象时出现 |
CASE_NOT_FOUNF |
在CASE语句中的选项与用户输入的数据不匹配时出现 |
COLLECTION_IS_NULL |
在给尚未初始化的表或数组赋值时出现 |
CURSOR_ALREADY_OPEN |
用户试图重新打开已经打开的游标时出现。在重新打开游标前必须先将其关闭 |
DUP_VAL_ON_INDEX |
用户试图将重复的值存储在使用唯一索引的数据库列中时出现 |
INVALID_CURSOR |
在执行非法游标运算(如fetch一个尚未打开的游标)时出现 |
INVALID_NUMBER |
将字符串转换为数字时出现 |
LOGIN_DENIED |
输入的用户名或密码无效时出现 |
NO_DATA_FOUND |
在表中不存在请求的行时出现 |
SOTRAGE_ERROR |
在内存损坏或PL/SQL耗尽内存时出现 |
TOO_MANY_ROWS |
在执行SELECT INTO语句后返回多行时出现 |
VALUE_ERROR |
在产生大小限制错误时出现。如,变量中的列值超出变量的大小 |
ZERO_DIVIDE |
以零做除数时出现 |
向一个NUMBER类型的变量赋值字符串时,导致异常的发生
SET ServerOutPut ON;
DECLARE
varNum NUMBER;
BEGIN
varNum := 'abc';
EXCEPTION
WHEN VALUE_ERROR THEN
dbms_output.put_line('VALUE_ERROR');
END;
使用SQLCODE , SQLERRM输出错误信息:
set serveroutput on;
declare
j integer:=0;
begin
j:='Jack';
--如果出错,直接去异常处执行,以下行不会输出
dbms_output.put_line('Value is setted');
exception
when others then
--在异常中默认使用sqlerrm输出信息
dbms_output.put_line(SQLCODE||'Other errors '||sqlerrm);
end;
/*while-loop 比loop好用多了*/
declare
v_sum integer := 0;
v_num integer := 0;
begin
v_num := '&num';
if v_num < 6 then
while v_sum < 6 loop
v_sum := v_sum + v_num;
dbms_output.put(v_num);
/*exit when v_sum = 6;*/
dbms_output.put('+');
v_num := v_num + 1;
end loop;
dbms_output.put('=');
dbms_output.put_line(v_sum);
elsif v_num >= 6 and v_num < 11 then
while v_sum < 11 loop
v_sum := v_sum + v_num;
dbms_output.put(v_num);
/*exit when v_sum = 11;*/
dbms_output.put('+');
v_num := v_num + 1;
end loop;
dbms_output.put('=');
dbms_output.put_line(v_sum);
else
while v_num < 19 loop
v_sum := v_sum + v_num;
dbms_output.put(v_num);
/*exit when v_sum = 19;*/
dbms_output.put('+');
v_num := v_num + 1;
end loop;
dbms_output.put('=');
dbms_output.put_line(v_sum);
end if;
end;
/*对type进行坐标管理形成的数组*/
declare
type dept_table_type is table of dept%rowtype index by binary_integer;
v_dept_table dept_table_type;
begin
select * into v_dept_table(0) from dept where deptno = 10;
select * into v_dept_table(1) from dept where deptno = 20;
dbms_output.put_line('编号:' || v_dept_table(0).deptno || ' 名称' || v_dept_table(0)
.dname);
dbms_output.put_line('编号:' || v_dept_table(1).deptno || ' 名称' || v_dept_table(1)
.dname);
end;