• 游标和触发器


    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);
  • 相关阅读:
    css 设置特定条件下的标签
    vue实现导航菜单滚动
    input 默认样式样式 样式修改
    vue 倒计时
    微信小程序 botton默认样式删除
    Notepad++ 快捷键
    css实现div水平垂直居中
    Python爬虫爬取1905电影网视频电影并存储到mysql数据库
    Python爬虫爬取搜狐视频电影并存储到mysql数据库
    第一阶段(十)
  • 原文地址:https://www.cnblogs.com/gavenQin/p/5577513.html
Copyright © 2020-2023  润新知