第六章 游标和触发器

版权声明:本文为博主原创文章,未经博主允许不得转载 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;

猜你喜欢

转载自blog.csdn.net/Mythology_px/article/details/82432614
今日推荐