Oracle PL/SQL
一. PL/SQL: 过程化语言,是专门为Oracle开发的一门语言。
1. PL/SQL块:3部分组成
1.1 声明部分(declare):可以省略
主要是用来定义一些变量,游标,类型等等。
1.2 执行部分(begin):不能省略
主要用来编写具体的业务逻辑执行的代码。
1.3 异常处理(exception):可以省略
主要用来捕获程序中出现的异常情况,并进行处理
语法:
[declare
变量声明:
类型声明:
游标定义: ]
begin
编写业务逻辑的代码执行:
[exception
异常处理的代码 ]
end;
注意:在PL/SQL块中每一条语句之后必须要使用";"结尾
2. 数据类型
2.1 简单的数据类型
(1)数值型:number,int
(2)字符串类型:char,varchar2,long
(3)时间类型:date,timestamp
(4)布尔类型:boolean:true/false
2.2 特殊数据类型
(1)%type:定义的变量的数据类型和某一张表中的指定字段的数据类型保持一致
语法:变量名 表名.字段名%type;
(2)record:记录类型,可以将多个变量封装成一个整体,在后续的使用过程中直接使用该记录
使用步骤:1. 定义一个记录类型(自定义数据类型)
type 记录名 is record(
变量名 数据类型,
变量名 数据类型,
......
);
2. 声明一个记录类型的变量
变量名 记录名
3. 在访问记录类型里面的变量的时候需要使用记录类型定义的变量来访问
记录名.变量名
例子: declare
type emp_datas is record(
id emp.eno%type,
name emp.ename%type,
sal emp.sal%type
);
edata emp_datas;
begin
select eno,ename,sal into edata from emp where eno = '01';
dbms_output.put_line(edata.id,edata.name,edata.sal);
end
(3)%rowtype:行类型,定义该类型的变量就相当于拥有该表中所有列的变量
语法:变量名 表名%rowtype;
3. 变量的定义
在内存中开辟存储空间来保存数据
语法:变量名 数据类型[长度] [:=初始值]
例子:a int := 10;
注意:定义变量的时候变量名必须符合规范,在赋值的时候要使用":=",变量的数据类型是字符串类型的时候需要写长度
4. 常量的定义
语法:常量名 constant 数据类型[长度] := 常量值
例子:a constant int := 10;
注意:常量定义时必须赋值
二. PL/SQL中的流程控制语句
程序结构有3种
1. 顺序结构:从上往下依次执行
2. 分支结构:根据条件结果选择不同的执行内容
(1)if:单分支语句
语法:if 条件判断 then
条件成立时执行的代码
end if;
(2)if ...... else ......:双分支语句
语法:if 条件判断 then
条件成立时执行的代码
else
条件不成立时执行的代码
end if;
(3)if ...... elsif ...... else:多分支语句
语法:if 条件判断1 then
条件1成立时执行的代码
elsif 条件判断2 then
条件2成立时执行的代码
...
else
条件不成立时执行的代码
end if;
(4)case ... when语句:进行等值匹配
语法:case 变量
when 值1 then
当变量的值等于值1时执行的代码
when 值2 then
当变量的值等于值2时执行的代码
....
else
以上的值都不等时执行的代码
end case;
3. 循环结构:在满足指定的条件的前提下,重复执行某一段代码
(1)loop:
语法:loop
循环体
exit when 循环条件;
循环体
end loop;
执行顺序:先执行循环体,然后判断循环条件,如果条件不成立则继续执行循环
如果条件成立则退出循环
(2)while:
语法:while 循环条件 loop
循环体
end loop;
执行顺序:判断循环条件,如果条件成立则执行循环体,如果条件不成立则退出循环
(3)for:
语法:for 循环变量 in [reverse] 下限..上限|游标名 loop
循环体
end loop;
注意:reverse:代表反转,相当于从上限到下限
三. 游标
在SQL语句执行的时候,系统会自动分配一块内存空间,用来保存sql语句执行所影响的数据,这一块空间就可以看作游标
游标分类
1. 显示游标:主要用来操作查询语句的查询结果(结果集)
特点:游标必须由用户自己定义
定义游标的语法:
cursor 游标名[(参数)] is
查询语句;
注意:游标在declare中定义
操作步骤:(1)定义游标(2)打开游标 语法:open 游标名 [(参数值)];(3)读取游标 语法:fetch 游标名 into 变量;(4)关闭游标
例子:
declare
cursor cur_emp is
select * from emp where deptno = 30;
row_emp emp%rowtype;
begin
open cur_emp;
loop
fetch cur_emp into row_emp;
exit when cur_emp%notfound;
dbms_output.put_line(cur_emp.ename);
end loop;
close cur_emp;
end;
使用for循环来操作游标:
语法:fro 变量名 in 游标名[(参数值)] loop
循环体
end loop;
例子:
declare
cursor cur_emp is
select * from emp where deptno = 30;
begin
for row_emp in cur_emp loop
dbms_output.put_line(cur_emp.ename);
end loop;
end;
游标的属性:
(1)%notfound:返回布尔类型的值,如果游标没有读取到数据则返回true
(2)%found:返回布尔类型的值,如果游标有读取到数据则返回true
(3)%rowcount:返回数字类型的值,返回游标影响的行数
(4)%isopen:返回布尔类型的值,如果游标打开返回true,没打开返回false
2. 隐式游标:主要用来操作DML(insert,update,delete等待)语句,也可以操作查询的结果集
在Oracle数据库中,每次执行SQL语句系统都会自动为该条语句创建一个游标,这一类游标就叫隐式游标
在Oracle数据库中所有的隐式游标统一名称——sql
使用隐式游标配合for 循环实现查询操作
语法: for 变量名 in (查询语句) loop
循环体
end loop;
例子:
begin
for row_emp in (select * from emp where deptno = 30;) loop
dbms_output.put_line(cur_emp.ename);
end loop;
end;
3. 引用游标(ref游标):在存储过程中如果要返回一个结果集则需要使用引用游标
暂时不写
四. 异常处理
语法:exception
when 异常名称1 then
异常处理代码
when 异常名称2 then
异常处理代码
异常的分类:
(1)系统的预定义异常:数据库中已经定义好的异常,我们可以直接拿过来使用
常见的异常有:
zero_divide:除数为0异常
no_date_found:使用select...into语句的时候没有查询到数据
too_many_rows:使用select..into语句的时候查询到多行数据
cursor_already_open:试图打开一个已经打开的游标
invalid_cursor:一个非法游标操作,试图关闭一个没有打开的游标
(2)用户自定义异常
(2.1)错误编号异常:将数据库中出现的一些异常编号,和一个异常变量进行绑定,在后续进行捕获
就可以直接使用异常变量来处理对应异常编号的异常
步骤:
1. 定义异常变量
变量名 exception;
2. 将异常变量名和错误编号进行绑定
pragma exception_init(异常变量名,错误编号);
3. 使用异常变量名来捕获异常
例子:
declare
exc exception;
pragma exception_init(exc,-00001);
begin
insert into dept(deptno) values(10);
exception
when exc then
dbms_output.put_line('主键不能重复!');
end;
注意:错误编号异常,其实也算是系统异常,异常的引发是由系统来完成的
(2.2)业务逻辑异常:是由用户根据自己的业务逻辑需要定义的异常,并且在规定的时间内由用户引发
步骤:
1. 定义异常变量
变量名 exception;
2. 在逻辑需要的时候进行引发异常
raise 异常变量名
3. 用户引发的异常必须要使用exception进行处理
例子:
declare
dname_null_exception exception;
r_dept dept%rowtype;
begin
r_dept.deptno:=21;
r_dept.loc:='深圳';
insert into dept values(r_dept.deptno,r_dept.dname,r_dept.loc);
if r_dept.dname is null then
raise dname_null_exception;
end if;
commit;
exception
when dname_null_exception then
dbms_output.put_line('部门名称不能为空');
rollback;
end;
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库