目录
概述:
PL/SQL是过程化的结构查询语言(Procedural Language/Structured Query Language),它可以弥补SQL语句的不足。
在PL/SQL中可以通过IF和LOOP语句控制程序的执行流程,并且可以定义变量,以便利用这些变量在语句之间传递数据信息。
PL/SQL是Oracle的专用语言,是对标准SQL语言的扩展,SQL语句可以嵌套在PL/SQL程序代码中,将SQL的数据处理能力和PL/SQL的过程处理能力结合在一起。
什么是PL/SQL?
PL/SQL块的主要组成部分:
声明部分、执行部分、异常处理部分。
格式:
说明:
注意规范:
标识符的命名规范
变量与数据类型
基本数据类型:Boolean、Binary_interger、Pls_interger、Number、Int、Char、Varchar2、Date、Long
详细使用可自行查阅资料
声明变量:
variable_name data_type [ [NOT NULL]:=default_value_expression]; --有初始值
variable_name data_type [ [NOT NULL] DEFAULT default_value_expression];--无初始值
NOT NULL表示变量不允许为空
变量定义举例:
SET SERVEROUTPUT ON --显示结果
declare
v_name varchar2(8):=‘PJ’; --变量声明
V_nowtime date:=sysdate;
begin
dbms_output.put_line(v_name); --显示输出
dbms_output.put_line(v_nowtime);
end;
/ --执行程序块
注意:使用DBMS_OUTPUT包来显示查询结果或文本行时,需先执行SET SERVEROUTPUT ON语句。
标量变量
%TYPE变量
var_name emp.ename%type;
又如何从表中拿到数据放进变量中呢 格式:into 变量名
select ename into v_name
from emp
where empno=7369;
复合类型的变量
定义格式 :v_name recode_name;
select * into v_name from 表名 --将表里面所有数据放入变量
![](https://i-blog.csdnimg.cn/blog_migrate/39f6a13eb86b4da9096cac85d65da64c.png)
自定义记录类型 (类似于结构体定义)
声明格式: type record_name is record(
字段名1 类型;
字段名2 类型;
.....
);
例:将emp表中工号为7369的职工的姓名(ename)、工种(job)、工资(sal)输出显示。
条件语句
if...then(单分支)
if <expression1> then --expression1判断条件
pl/sql_statement;--符合if条件后要执行的pl/qsl语句
end if;
if...then..else(双分支)
if <expression1> then
pl/sql_statement1;
else
pl/sql_statement2;
end if;
if...then ...elsif(多分支)
if < expression1> then
pl/sql_statement1;
elsif < expression2> then ---注意这里是elsif,和我们平常的习惯可能不同
pl/sql_statement2;
……
else
pl/sql_statement3;
end if;
case (不使用选择器)
case
when expression 1 then pl/sql_statement1; --判断每个when子句的条件
when expression 2 then pl/sql_statement2;
....
when expression n then pl/sql_statementn;
[else expression n+1 then pl/sql_statement;]
end;
case(使用选择器)
case <selector>
when <expression1> then pl/sql_statement1; --获取选择器的值,和每个when子句进行比较判断
when <expression 2> then pl/sql_statement2;
....
when <expression n> then pl/sql_statementn;
[else <expression n+1> then pl/sql_statement;]
end;
循环语句
LOOP循环
loop
statements;--循环体
exit when condition;--跳出判断
end loop;
WHILE循环
while condition --适用于事先无法知道控制循环终止变量值的情况。
loop
statements;
end loop;
FOR循环
for loop_variable_name in [reverse] lower_bound..upper_bound
-- loop_variable_name 是指定循环计数器,可以使用已经有的,也可以使用一个新的。
-- 省略reverse,就是升序,不省略就是逆序。
-- for循环会自己,自增或自减1.不能在循环体里动态的去改变loop_variable_name的值
loop
statements;
end loop;
游标的使用
SQL 提供游标机制来实现在程序设计语言中处理集合。
游标的作用就相当于指针,通过游标程序设计语言就可以一次处理查询结果集中的一行。
在Oracle中,游标可以分为两大类:静态游标和REF游标。
隐式游标
在执行一个SQL语句时,Oracle会自动创建一个隐式游标。这个游标是内存中处理该语句的工作区域,在其中存储了执行SQL语句的结果。通过游标的属性可获知SQL语句的执行结果,以及游标的状态信息
游标的主要属性:
当使用隐式游标时,需要在前面加SQL(默认的游标名)
cursor for loop语句:对SQL语句返回的结果集进行处理
for 游标变量 in select语句
loop
DML操作
end loop;
![](https://i-blog.csdnimg.cn/blog_migrate/0a896a1c3da055d8fdb029e8d13a5548.png)
显式游标
--定义游标:
Cursor 游标名 is select语句; --不带参数的游标
Cursor 游标名(参数名1 类型名1,参数名2 类型名2,……) is select语句; --带参数的游标
--打开游标
open 游标名;
open 游标名(实参值1,实参值2,……)
--提取游标数据
fetch 游标名 into 记录变量名;
--关闭游标。
close 游标名;
举例:
游标for循环
游标通常是与循环联合使用。实际上,PL/SQL还提供了一种将两者综合在一起的语句,即游标FOR循环语句。游标FOR循环是显式游标的一种快捷使用方式,它使用FOR循环依次读取结果集中的数据。当FOR循环开始时,游标会自动打开(不需要使用OPEN方法),每循环一次系统自动读取游标当前行的数据(不需要使用FETCH),当退出FOR循环时,游标被自动关闭(不需要使用CLOSE)
--在SCOTT模式下显示工资排名前5的员工的编号、姓名和工资。
declare
cursor emp_cur is select empno,ename,sal from
(select empno,ename,sal from emp order by sal desc) where rownum<6;
begin
for i in emp_cur loop
dbms_output.put_line(i.empno|| ' ' || i.ename|| ' '|| i.sal);
end loop;
end;
/
异常处理
在编写PL/SQL程序时,不可避免地会出现一些错误。在Oracle系统中使用异常来处理这些错误,这些异常都可以包括在PL/SQL程序的EXCEPTION块中。Oracle系统提供了许多内置的异常,用户也可以根据自己的需要定义异常
Oracle系统中的异常可以分为3类:
预定义的异常:Oracle提供,用户无需在程序中定义,由Oracle自动引发。
非预定义异常:数据库本身不知道、不能控制的错误。需要用户在程序中定义,然后由Oracle自动引发。
用户定义的异常:违反了业务逻辑,程序员可以明确定义并引发。
预定义的异常
举例:
使用SQLCODE、SQLERRM函数进行异常处理
非预定义异常
在一个异常产生、被捕获并处理之前,它必须被定义。Oracle定义了几千个异常,绝大多数只有错误编号和相关描述,仅仅命名了21个最常被用到的异常,即系统预定义异常。这些异常的名称被储存在STANDARD,UTL_FILE,DBMS_SQL这几个系统包中。
使用pragma exception_init语句可以为错误关联一个名字
--已知Oracle中一错误代码ORA-01400: 无法将 NULL 插入,
--请将该错误代码与NULL_INSERT_ERROR进行关联,并利用Scott模式下的表(
--例如,emp或dept)操作,举例报出该错误。
declare
null_insert_error exception;
pragma exception_init(null_insert_error,-1400);
begin
insert into emp(empno) values(NULL);
exception
when null_insert_error then
dbms_output.put_line('无法将NULL插入');
end;
用户定义的异常
程序开发人员可以根据具体的业务逻辑规则,自定义一个异常。这样,当用户操作违反了业备逻辑规则后,就引发一个自定义异常,从而中断程序的正常执行,并转到自定义的异常处理部分。
--定义异常处理
declare
异常名 exception;
--触发异常处理
raise 异常名;
--处理异常,在exception,中处理
--自定义一个异常,在SCOTT模式下,如果查找到EMP表中的某一员工
--(员工编号由用户任意输入)的佣金(COMM字段)为0时,则显示自定义错误消息“该员工的佣金为0”。
declare
v_sal emp.sal%type;
e_sal exception;
v_eno emp.empno%type:=&no;
begin
select sal into v_sal from emp where empno=v_eno;
if emp_cur.sal=0 then --触发异常的逻辑判断
raise e_sal;
exception
when e_sal then
dbms_output.put_line('该员工的佣金为0!');
end;
/