版权声明:本文为博主原创文章,未经博主允许不得转载 https://blog.csdn.net/Mythology_px/article/details/82432614
游标
游标是用来查询数据、获取结果集中记录的指针,指向结果集数据缓冲区中的某一行
静态游标
隐式游标
PL/SQL为所有数据操纵语言隐式声明游标; 隐式游标自动声明、打开,隐式游标执行完DML语句后自动关闭,其名为SQL; 通过检查游标的属性可以获取与最近执行的SQL语句的相关信息
- 隐式游标的属性有:
- %found – SQL 语句影响了一行或多行时为 TRUE
- %notfound – SQL 语句没有影响任何行时为TRUE
- %rowcount – SQL 语句影响的行数
- %isopen - 游标是否打开,始终为FALSE
--隐式游标属性
declare
v_ename emp.ename%type;
begin
select ename into v_ename from emp where empno=7788;
dbms_output.put_line('DML语句影响的行数:' || SQL%rowcount);
if sql%found then--返回记录行数>=1,true
dbms_output.put_line('Yes,founded');
else
dbms_output.put_line('NO,not found');
end if;
if sql%notfound then--没有影响任何行,true
dbms_output.put_line('yes,notfound');
else
dbms_output.put_line('NO,founded');
end if;
if sql%isopen then
dbms_output.put_line('游标打开');
else
dbms_output.put_line('游标关闭');
end if;
end;
显式游标
对于返回多条记录的查询,需要使用游标逐条处理这些数据,显式游标在 PL/SQL 块的声明部分定义查询,该查询可以返回多行
--显式游标--单行数据
declare
--声明显式游标,将一个查询语句绑定到游标
cursor myemp is select * from emp where empno=7788;
emp_row emp%rowtype;
begin
--打开游标
open myemp;
--提取数据
fetch myemp into emp_row;
dbms_output.put_line(emp_row.ename);
--关闭游标
close myemp;
end;
--显式游标--多行
declare
--声明显式游标,将一个查询语句绑定到游标
cursor myemp is select * from emp;
emp_row emp%rowtype;
begin
--打开游标
open myemp;
--提取数据
loop
fetch myemp into emp_row;
--当游标指向结果集最后一条记录,并且无法成功fetch数据,则返回true
exit when myemp%notfound;
dbms_output.put_line(emp_row.ename);
end loop;
--关闭游标
close myemp;
end;
--for循环显式游标
declare
--声明游标
cursor myemp is select * from emp;
begin
/*
for循环游标,游标自动打开,
自动从结果集中获取行,
然后在处理完数据后自动关闭游标.
记录索引变量:不需要声明,自动为%rowtype类型;
*/
for i in myemp loop
dbms_output.put_line(i.ename);
end loop;
end;
动态游标:ref游标、引用游标
运行时动态执行的 SQL 查询; 静态游标在声明时就为游标绑定了查询语句,而引用游标在打开时为游标绑定语句
--ref游标
declare
--声明ref cursor类型
type ref_cursor is ref cursor;
--使用声明的类型定义游标变量
mycur ref_cursor;
--定义行类型变量
emp_row emp%rowtype;
dept_row dept%rowtype;
begin
--打开引用游标:动态的指向查询语句
open mycur for select * from emp;
loop
fetch mycur into emp_row;
exit when mycur%notfound;
dbms_output.put_line(emp_row.ename);
end loop;
--关闭引用游标
close mycur;
--打开引用游标:动态的指向查询语句
open mycur for select * from dept;
loop
fetch mycur into dept_row;
exit when mycur%notfound;
dbms_output.put_line(dept_row.dname);
end loop;
--关闭引用游标
close mycur;
end;
存储过程和游标的用法
存储过程也可以使用游标,游标类型为sys_refcursor,存储过程可以使用输出类型游标也可以使用输入类型游标
--传出类型参数游标
create or replace procedure pro_1(mycur out sys_refcursor)
is
begin
--将传出参数动态游标打开指向查询语句
open mycur for select * from emp;
end;
--调用传出类型参数游标
declare
cur sys_refcursor;
emp_row emp%rowtype;
begin
pro_1(cur);
--提取数据
loop
fetch cur into emp_row;
exit when cur%notfound;
dbms_output.put_line(emp_row.ename);
end loop;
--关闭游标
close cur;
end;
--传入类型参数游标
create or replace procedure pro_2(mycur in sys_refcursor)
is
dept_row dept%rowtype;
begin
--提取数据
loop
fetch mycur into dept_row;
exit when mycur%notfound;
dbms_output.put_line(dept_row.dname);
end loop;
--关闭游标
close mycur;
end;
--调用传入类型参数游标
declare
cur sys_refcursor;
begin
--将动态游标打开指向查询语句
open cur for select * from dept;
pro_2(cur);
end;
触发器
触发器是特殊的PL/SQL块,该PL/SQL块是在特定的事件出现时,自动调动的; 触发器由触发器事件,触发器限制,触发器操作组成.
触发器类型:
行级触发器:SQL语句对数据影响的每一行都触发,只有行级触发器有new,old
语句级触发器:即表级触发器,针对SQL语句对数据的操作,触发器只激发一次
--行级触发器
create or replace trigger tri_dept_row
after insert or update or delete--指定触发器事件的数据操纵类型
on dept--指定触发器检查的表
for each row--指定受影响的每行都激发触发器
--PL/SQL块
declare
begin
if inserting then
dbms_output.put_line('dept表中增加数据');
elsif updating then
dbms_output.put_line('dept表中更新数据');
elsif deleting then
dbms_output.put_line('dept表中删除数据');
end if;
end;
--激发行级触发器:影响的每行都会激发触发器,不存在的不会激发
insert into dept values(50,'XiaoShouBu','Dali');
update dept set loc='DaLi';--影响多行,每行都会激发
update dept set loc='DaLi' where deptno=80;
delete from dept where deptno=50;
--行级触发器:限制条件
create or replace trigger tri_emp_row
after update
on emp
for each row
when (new.sal>old.sal)--限制触发条件
/*
new和old是记录对象,
在update中new表示新更新的数据,old表示更新前的旧数据
在insert中new表示插入的数据,old没有意义
在delete中new没有意义,old表示删除之前的数据
*/
declare
insal number(11);
begin
/*
在PL/SQL引用new和old需要使用":new",":old"
*/
insal := :new.sal - :old.sal;
dbms_output.put_line('工资增加:' || insal);
end;
--激发行级触发器:只有达到限制条件才可以激发触发器
update emp set sal=8000 where empno=7369;
update emp set sal=800 where deptno=7499;
delete from emp where empno=7788;
--创建语句级触发器
create or replace trigger tri_dept
after insert or update or delete
on dept
--没有for each row 就是语句级触发器
begin
if updating then
dbms_output.put_line('emp中的数据已更新');
elsif deleting then
dbms_output.put_line('emp中的数据已删除');
elsif inserting then
dbms_output.put_line('emp中添加了数据');
end if;
end;
--激发语句级触发器:影响多行,只会激发一次,不存在的也会激发
insert into dept values(50,'XiaoShouBu','Dali');
update dept set loc='DaLi';--影响了多行,激发了一次
update dept set loc='DaLi' where deptno=80;
delete from dept where deptno=50;
--使用触发器实现ID自增
--创建表
create table stu(
id number primary key,
name varchar2(20)
);
--创建序列
create sequence seq_id;
--创建触发器
create or replace trigger ter_stu
before insert
on stu
for each row
begin
select seq_id.nextval into :new.id from dual;
end;
--插入数据触发行级触发器,使其自动增加id
insert into stu values(null ,'Zhang');
insert into stu values(null,'Liu');
insert into stu(name) values('Li');
触发器管理
启用和禁用触发器
--禁用触发器
alter trigger ter_stu disable;
--启用触发器
alter trigger ter_stu enable;
删除触发器
--删除触发器
drop trigger ter_stu;