--NO_DATA_FOUND 异常
declare
v_name t_student.name%type; --学生姓名
v_edu t_student.edu%type; --学历
v_msg varchar2(100);
begin
select name,edu into v_name,v_edu from t_student where id=100;
v_msg:=v_name||v_edu;
dbms_output.put_line(v_msg);
exception --捕捉异常
--判断是否是我们需要的异常
when no_data_found then
--处理异常
dbms_output.put_line('没有找到数据');
--when others 可以用于捕获其他的异常
when others then
dbms_output.put_line('其他异常');
--处理异常
end;
3、自定义异常
--自定义异常方式 声明变量时,类型为exception
--抛出异常 raise 异常名称。
在插入学员数据时,如果性别为其他数据时显示异常输出“请正确输入性别值”
declare
v_row t_student%rowtype;
--声明自定义异常
exc_sex exception;
begin
select seq_student.nextval into v_row.id from dual;
v_row.name:='李大明白';
v_row.sex:=1;
v_row.edu:='本科';
v_row.tele:=null;
v_row.cardno:=null;
v_row.classid:=1;
if v_row.sex not in (0,1) then
--抛出异常
raise exc_sex;
end if;
insert into t_student values(seq_student.nextval,v_row.name,
v_row.sex,v_row.edu, v_row.tele,v_row.cardno,v_row.classid);
commit;
exception
--捕捉异常
when exc_sex then
dbms_output.put_line('请正确输入性别值');
end;
格式:
CREATE [or REPLACE] TRIGGER 触发器名
BEFORE | AFTER
[DELETE ][[or] INSERT] [[or]UPDATE [OF 列名]]
ON 表名
--for each row 的意思是行级触发器 行级触发器每修改一行,执行一次
--不写,默认为语句级触发器,语句级触发器的作用是,无论修改多少行,只执行一次。
[FOR EACH ROW [WHEN(条件) ] ]
declare
……
begin
PLSQL 块
End ;
解释:
trigger 表示触发器的意思
触发器名称建议trigger_xxx
before|after表示触发器执行时间,before表示触发器在事件执行之前执行,
after表示触发器在事件执行之后执行。
dlelet|insert|update表示激活触发器的事件
表名是指触发器操作的表的名称。
for each row 表示任何一条记录上的操作都会激活触发器。
PLSQL块,表示触发器激活之后,执行的SQL语句。
在触发器中触发语句与伪记录变量的值
触发语句 :old :new
Insert 所有字段都是空(null) 将要插入的数据
Update 更新以前该行的值 更新后的值
delete 删除以前该行的值 所有字段都是空(null)
3、使用触发器
--before触发器
--案例需求:班级,插入班级信息时,自动指定班级id
--创建触发器
create trigger tri_class
before insert on t_class for each row
begin
select seq_class.nextval into :new.id from dual;
end;
--执行插入记录,测试触发器是激活
insert into t_class(name,type,state,opendate) values('实验班31班',2,1,to_date('2016-06-10','yyyy-mm-dd'));
select * from t_class order by id;
--after触发器
--修改学员的学历时自动记录修改前和修改后的学历
--建表
create table t_edu_log(
id number primary key,
update_date date,
studentid number,
edu0 varchar2(30),--修改之前的学历
edu1 varchar2(30) –修改后的学历
);
--创建序列
create sequence seq_log;
创建触发器
create or replace trigger tri_student_edu_update
after
update of edu
on t_student
for each row
declare
begin
--:old :new
insert into t_edu_log values (seq_log.nextval,sysdate,
:old.id,:old.edu,:new.edu
);
end;
三、游标
1、游标简介
在写java程序中有结果集的概念,那么在pl/sql中也会用到多条记录,
这时候我们就要用到游标,游标可以存储查询返回的多条数据。
游标可以理解为是PL/SQL中的结果集,我们通过游标可以提取结果集中的每行记录。
游标可以看作一种数据类型,可以用来遍历结果集,相当于指针,或者数组中的下标。
处理结果集的方法可以通过游标定位到结果集的某一行,从当前结果集的位置搜索一行或一部分
行或者对结果集中的当前行进行数据修改。
for 循环遍历游标的时候,变量默认声明为rowtype类型
2、使用游标
2.1声明游标
声明游标要写到declare下,类似于声明变量
语法格式(Oracle数据库)
declare
cursor cursor_name is SQL语句;
2.2打开游标
open cursor_name;
2.3使用游标
open 游标名称
loop
--使用的变量一般是记录型引用
--遍历游标使用fetch into 关键字
fetch 游标名称 into 变量
--判断游标是否结束 游标名称%notfound
exit when 游标名称%notfound
end loop;
close 游标名称
2.4关闭游标
close cursor_name;
2.5游标使用案例
--例如 需求 控制台输出女学员信息
--声明游标
select * from t_student where sex='0';
declare
cursor cursor_girl is select * from t_student where sex='0';
v_student t_student%rowtype;
begin
--开启游标
open cursor_girl;
loop
fetch cursor_girl into v_student;
exit when cursor_girl%notfound;
--如果输出语句放在exit上面,最后一条记录会输出两遍,因为当第一次输出最后一条记录后,
--判断notfound为true,之后,输出语句会再次执行一次,所以总共执行两次
dbms_output.put_line(v_student.ID||' '|| v_student.NAME||' '||v_student.SEX);
end loop;
--关闭游标
close cursor_girl;
end;
2.6有参数的游标
--当声明游标时如果参数暂时不能指定,可使用有参数的游标
--声明游标时,游标名称(参数) where 字段=参数
--开启游标时,传入参数 open cursor_name(实际参数);
declare
cursor cur_student(v_sex number) is select * from t_student where sex=v_sex;--声明游标
r_student t_student%rowtype;--学员表行类型
begin
open cur_student(1);--打开游标
loop
fetch cur_student into r_student ;
exit when cur_student%notfound;--退出循环
dbms_output.put_line( '学员姓名:'||r_student.name || ' 身份证号'||r_student.cardno );
end loop;
close cur_student;--关闭游标
end ;
--使用for循环遍历游标,更加简单,简化了开启游标,遍历游标的过程
declare
cursor cur_student(v_sex number) is select * from t_student where sex=v_sex;--声明游标
begin
for r_student in cur_student(1)
loop
dbms_output.put_line( '学员姓名:'||r_student.name || ' 身份证号'||r_student.cardno );
end loop;
end ;
2.7 系统引用游标
--声明游标时,类型为sys_refcursor
--初始化游标使用 open 游标名 for 'SQL语句'
--之后游标的使用和普通游标的使用是一样的
declare
--声明系统引用游标
cur_girl sys_refcursor;
v_student t_student%rowtype;
begin
--初始化系统引用游标
open cur_girl for select * from t_student where sex='0' ;
loop
fetch cur_girl into v_student;
-- dbms_output.put_line(v_student.ID||' '|| v_student.NAME||' '||v_student.SEX);
exit when cur_girl%notfound;
-
dbms_output.put_line(v_student.ID||' '|| v_student.NAME||' '||v_student.SEX);
end loop;
--关闭游标
close cur_girl;
end;
2.8 隐式游标
--不需要声明,就直接使用的游标,相当于系统直接提供的游标,游标名称固定为SQL
--作用:通过隐式游标的属性,可以获取刚才执行语句的结果
--属性 %found:之前执行的SQL语句有结果
%notfounde 之前执行的SQL语句没结果
declare
v_name varchar2(111);
begin
select name into v_name from t_student where id=2;
if SQL%notfound then
dbms_output.put_line('1');
else
dbms_output.put_line('21');
commit;
end if;
end;
CREATE [ OR REPLACE ] FUNCTION 存储函数名称
(参数,参数,参数)
RETURN 数据类型
IS
变量声明部分;
BEGIN
逻辑部分
return 返回值
END;
--创建存储函数举例
--创建一个函数,通过传入学生id,就可以返回学生name
create or replace function fun_getnamebyid(v_id number)
return varchar2
is
v_name varchar2(30);
begin
select name into v_name from t_student where id=v_id;
return v_name;
--需要处理异常
exception
when no_data_found then
return '--';
end;
3、调用存储函数
调用函数的方法比较简单,和调用Oracle内置函数的方法一致,函数名(参数)即可
begin
dbms_output.put_line(fun_getnamebyid(3));
end;