HELLO,WORLD

游标和触发器

Oracle
  1、游标
  2、利用游标,读取所有数据
  3、利用存储过程,读取所有数据
  4、触发器
  
----------------------------------------------------

什么是存储过程?
答:存储过程是提前编写好,并且存储在数据库中的语句块,只要调用,即可马上运行

什么存储过程的好处?
答:  1、信息存储在数据库中,所以安全性会更好
     2、由于语句块本就存在数据库中可以直接运行,所以,速度会更快
     3、复用性会更好
     
--------------------------------------------------------
create or replace procedure my_pc(in_out_id in out number,out_name out varchar2,out_score out number)
as
begin
      select *  into in_out_id,out_name,out_score from inf where  id=in_out_id;
end;

------------------------------------
declare
      myid number(11):=1;
      myname varchar2(20);
      myscore number(11);
begin
      
      my_pc(myid,myname,myscore);
      dbms_output.put_line('编号:'||myid);
      dbms_output.put_line('姓名:'||myname);
      dbms_output.put_line('成绩:'||myscore);
end;


--------------------------------------------------------------------------------------------------------------------


cursor---游标

游标:  它是指向数据表中,某一条数据的一个指针,游标指向哪一行,这一行数据才可以读取

游标的分类:  静态游标  与  动态游标

        静态游标:--在创建游标时,就必须指定该游标关联的是哪一张表. (并且关联以后,就不能再改变)
        
        动态游标:--在创建的时候,不必指定关联的是哪一张表,用的时候再指定(并且可以改变)



游标

      静态游标
        
           隐式游标: --不需要用户创建,系统内置一些静态游标
           
                 *****隐式游标主要有三种:
                 sql%found  ---语句执行成功,返回true,执行失败返回false
                
                 sql%notfound---语句执行成功,返回false,执行失败返回true
                 
                 sql%rowcount --返回成功执行的语句的行数
                                        
                                        
           显示游标: --需要用户自己创建的静态游标
      
      动态游标
select * from inf ORDER BY ID;
----------------------------------------------------------
--静态游标--->隐式游标

declare
      myid number(11);
begin
      myid:=&请输入你要删除的学生编号;
      delete from inf where id>myid;
      
      if(sql%found)
             then
                   dbms_output.put_line('删除成功');
                   dbms_output.put_line('被删除的行数为:'||sql%rowcount);
      else 
             dbms_output.put_line('删除失败');                    
      end if;       
      
end;
-------------------------------------------------------


静态游标--->显示游标    

--静态游标:  在声明游标的时候,就必须指定关联的是哪一张表

使用步骤:
      1、声明游标
      2、打开游标
      3、利用游标提取数据
      4、关闭游标
--------------------------------------------------------------
declare
      cursor my_cr is select * from inf order by id; --声明游标读取inf表的数据
      r inf%rowtype;
begin
      open my_cr; --打开游标
      fetch my_cr into r; --让游标向下移动一位,并且把游标指向的这一行数据,赋值给r
      dbms_output.put_line(r.id||'  '||r.name||'   '||r.score);
      close my_cr;--关闭游标
end;

------------------------------------------------------------  ************静态游标-----显示游标
declare
      cursor my_cr is select * from inf order by id;  --声明游标
      r inf%rowtype;
begin
      open my_cr; --打开游标
      fetch my_cr into r; --游标向下移动一位,并且把这一行数据赋值给变量r
      
      while(my_cr%found)   --my_cr%found 如果游标指向的这一行存在数据,返回true,没有数据,返回false
            loop
                           dbms_output.put_line(r.id||'  '||r.name||'   '||r.score);
                           fetch my_cr into r;                       
            end loop;
      close my_cr; --关闭游标            
end;

----------------------------------------------------------------------------------------------------------------
动态游标 : --这种游标,在声明游标的时候,不需要指定关联的是哪一张表,在打开游标的时候,再指定

declare
     type mycr is ref cursor;  --声明一种类型,这种类型为游标类型
     c_r  mycr;  --声明一个变量,变量为c_r,它是一种游标类型的变量
     
     r inf%rowtype;  --声明行变量,用于保存读取的数据
begin
     open c_r for select * from inf order by id;  --打开游标,并且指定关联的表
     
     fetch c_r into r; --利用游标提取数据
     
     while(c_r%found)
           loop
                dbms_output.put_line(r.id||'  '||r.name||'   '||r.score);
                 fetch c_r into r;--指向下一行
           end loop;
     close c_r;
end;


---------------------------------------------------------
oracle的 PL/SQL语句块中,声明的变量\游标这些对象,使用完成以后,就会马上销毁,它们自身无法保存

----
如果将这些变量\游标存放一个对象中,它们就可以永久保存下来-------------------该对象称为:   程序包 package

--创建程序包

create or replace package my_pk
as

       type my_cr is ref cursor;
end;

----
--创建存储过程,返回游标
create or replace procedure my_pc(in_score in number,out_cr out my_pk.my_cr)
as
begin
      open out_cr for select * from inf where score>=in_score order by score desc;
end;
select user from dual;

-----------------------------------------------------------------------------------------------------------------------
*******************************************************

触发器  trigger

什么是触发器?它有什么用?

答:触发器是存储在数据库中代码块,当用户的操作满足某一条件时,系统将自动调用触发器的中代码;


*********注意:其实触发器只能被系统调用,不能被用户调用

--触发器的分类:

       1、行级触发器
       2、表级触发器
       3、instead of 触发器(视图触发器)
       4、模式触发器

------------------------------------------------------------------------------------------------------
行级触发器:  当用户对表中的某一行数据进行操作时,触发了设置的触发条件时,触发器中的代码就会自动运行

--行级触发器语法:
create or replace trigger 触发器的名称
before 动作名称 onfor each row
begin
       触发器要执行的代码;
end;

----------------------------------------------
示例: --对表添加的数据时候,触发

create or replace trigger tr_inf_insert

before insert on inf for each row

begin
       dbms_output.put_line('用户向数据表中添加到了一行数据');
end;

--如果对表进行了修改,删除,添加,都触发

create or replace trigger tr_inf_insert

before insert or update or delete on inf for each row

begin
       dbms_output.put_line('用户操作了表中的数据');
end;



--------------------------------------------------------------------
利用行级触发器,限制新员工在本公司的工作年限都为0

create table empInfo
(
       eid number(11) primary key,
       ename varchar2(20) not null,
       work_years number(11) default 0   --所有新入职的员工在本公司的工作年限都应该为0
);

--------------------------------------
--   :new.work_years  表示:即将赋给inf表中work_years字段的新值

create or replace trigger tr_empInfo_insert
before insert on empInfo for each row
begin
       if(:new.work_years>0)                --如果要添加的工作年限大于0,就把它改为0
              then 
                 :new.work_years:=0;
       end if;          
end;

insert into empInfo values(1,'tom',10);

update empInfo set work_years=5 where eid=1;
select * from empInfo;


--------------------------------

    create table province
    (
           pid number primary key,
           pname varchar2(20)
    );
    insert into province values(1,'湖北省');
    
    create table city
    (
           cid number primary key,
           cname varchar2(20),
           pid number,
           foreign key (pid) references province(pid)
    );
    insert into city values(1,'武汉市',1);
---------------------------------------------------------
select * from province;
select * from city;
delete from province where pid=1;

-------------------------------------------------------------
** 通过触发器,在删除主键表数据的时候,由触发器提前把关联的外键数据删除
create  or replace trigger tr_province_delete
before delete  on province for each row
begin
       delete from city where pid=:old.pid;  --如果城市表中的pid字段等于要删除的省份表中pid字段,就这对应城市信息删除
end;

------------------------------------------------------------

********注意:   

:new.xxx

:old.xxx
这两个属性,只有在行级触发中才可以使用

-------------------------------------------------------------------------------------------------------------------------
*************表级触发器
--不包含  for each row 的触发器就是表级触发器

select user,sysdate from dual;  -- user  获得当前用户          sysdate   获得系统时间

--------------------****************表级触发器

******创建表,实现日志记录
create table inf_log
(
       log_id number primary key,
       op_name varchar2(20),--用户名
       op_time date,--操作时间,
       op_details varchar2(100) --做了什么操作
)
create sequence inf_log_seq; --创建序列

--如果执行的是insert操作, 系统的inserting属性会返回true

--如果执行的是update操作, 系统的updating属性会返回true

--如果执行的是delete操作, 系统的deleting属性会返回true


create or replace trigger tr_inf_operation
before insert or update or delete on inf
begin
       if inserting 
          then  insert into inf_log values(inf_log_seq.nextval,user,sysdate,'向数据表添加了数据');
       elsif updating
          then  insert into inf_log values(inf_log_seq.nextval,user,sysdate,'修改了数据表中的数据');    
       elsif deleting
          then  insert into inf_log values(inf_log_seq.nextval,user,sysdate,'删除了数据表中的数据'); 
       end if;   
end;

select * from inf_log;

delete from inf where id=13;
update inf set name='other' where id=3;
insert into inf values(13,'aaa',99);

 

posted @ 2016-06-12 14:50  秦正全  阅读(432)  评论(0编辑  收藏  举报