• 1.索引、事务、触发器、存储过程、游标、程序包


    pl/sql基本语法

    -----------------------自定义异常--------------------------------------------------------------------

    定义部分: 声明异常变量   exception_name   exception;

    执行部分:抛出异常  raise  exception_name;

    异常处理部分: 捕获异常

     

    ------------------------创建过程----------------------------------------------------------------------

      create or replace procedure procedure_name(参数)
      is / as
        local variable declaration
      begin
        executable   statements
      exception 
        exception handlers
      end;

         

    执行存储过程: in 模式调用存储过程exec   procedure_name()

                              out 模式调用存储过程时,需要在其他pl/sql中进行调用

                              inout模式调用存储过程时,需要在其他pl/sql中进行调用

    过程参数三种模式

    in:用于接受调用程序的值

          默认的参数模式

    out :用于向调用程序返回值

    in out:用于接受程序的值,并向调用程序返回更新的值

     例 1:编一个 输入两个数字并使得两个数字交换输出的存储过程

    定义    

     create or replace procedure  procedure1(p1 in out number, p2 in out number)
      as
      v_temp number;
      begin
        v_temp :=p1;
        p1 := p2;
        p2 :=v_temp;
      end;

    调用:

      

    declare 
        num1  number :=100;
        num2  number :=200;
      begin 
        proceduref1(num1,num2);
        dbms_output.put_line( 'num1 =' || num1,'num2 =' ||num2);
      end;

       

    --------------------------------函数---------------------------------------------------------------------------------

    函数是可以返回值的命名的pl/sql子程序

    定义函数的一些限制 :函数只能接受in参数,而不能接受out  或者 in out模式参数

              形参不能是pl/sql类型,只能是数据库类型

              函数的返回类型也必须是数据库类型

    创建函数的语法:

    create or replace function function_name(参数)
      return 数据类型
      as
        变量
      begin
        executable statements;
        return result;
      exception
        exception handlers;
      end;

    例1: 

     create or replace function function1 return varchar2
       as
         begin
        return   ‘你好,朋友’;
         end;

      sql.plus 中调用函数方法:  

    select  function1  from  dual;

      在pl/sql代码块中运行方法:

    declare
      ss  varchar2(20);
       begin
      ss:=function1;
           dbms_output.put_line(ss);
        end;

    例2:创建一个函数,可以接受用户输入的学号,得到该学生的名次,并输出这个名次

    学生成绩表(sno,name,score)

      

    create or replace function function2(sno1 int) return int
      as
      score1  number;
      mingci1 number;
      begin 
        select   score into  score1 from  student  where  sno = sno1;
        select   count(*)  into  mingci1  from student  where  score >score1;
        return  mingci+1;
      end;

    -------------------------        索引       ---------------------------------------------------------------------------

    索引分类:B树索引、位索引

    1.创建标准索引

       create index index_name 
       on  table_name(column1…);

    2,创建唯一索引

    create unique index  index_name 
    on table_name(column1…);

    3,.创建位索引 

    create bitmap index index_name
    on  table_name(column1…);

    ------------------------------------     事务       -----------------------------------------------------------

    原子性、一致性、隔离性、永久性

    设置自动提交:set autocommit on/off

    -----------------------------------      游标     --------------------------------------------------------------------

    游标分类:隐式游标:在pl/sql程序中执行dml sql语句时自动创建隐式游标,名称固定:sql

         显示游标 :显示游标用于处理返回多行的查询

         ref游标 :ref游标用于处理运行时才能确定的动态sql查询的结果

    游标的四种属性:

      %found         sql语句影响了一行或者多行时为true

      %notfound    sql语句没有影响任何行时为true

      %rowcount    sql语句影响的行数

      %isopen        游标是否打开

    声明游标、打开游标、提取游标数据、关闭游标 

    两个常见异常 :

      没有查找出数据:no_date_found

        返回过多行数:too_many_rows

     

    例1 使用游标取出学生记录表中的所有记录 student(sno,sname,sage) 

    declare
        stu1  student%rowtype;
        cursor  mycursor  is select  * from student;
      begin
        open  mycursor;
        fetch mycursor  into stu1  ;
        while  mycursor%found loop
          dbms_output.put_line('学号是:'  || stu1.sno || '学生名为:' || stu1.sname ||'学生年龄为;' || stu1.sage);    
                  end  loop;
        close mycursor;
      end

    对显示游标添加参数

      

    declare
        sno1 student.sno%type;
        stu1  student%rowtype;
        cursor  mycursor( input_no  number)  is select  * from student where  sno >input_no;
      begin
        sno1 :=&学生学号;
         open  mycursor(sno1);
        fetch mycursor  into stu1  ;
        while  mycursor%found loop
          dbms_output.put_line('学号是:'  || stu1.sno || '学生名为:' || stu1.sname ||'学生年龄为;' || stu1.sage);    
                  end  loop;
        close mycursor;
      end

    允许使用游标删除或更新活动集中的行   声明游标时必须使用  select …for  update语句

     声明时 

     cursor cursor_name is select  statement  for update;

     在更新语句时  

    update table_name   
    set set_clause
    where  current of cursor_name   --当缺少该行时,会对表中的所有数据行进行更新两次

    例3:使用游标  对2号或者3号的学生进行记录修改

     declare
        stu1  student%rowtype;
        cursor  mycursor  is select  * from student where sno=2 or sno =3 for update;
      begin
        open  mycursor;
        fetch mycursor  into stu1  ;
        while  mycursor%found loop
          update student
          set sno = sno +10;
          where current of mycursor;
          fetch  mycursor into stu1;   
                  end  loop;
        close mycursor;
      end

    显示游标例

      两张表  student(xh number , xm varchar2(10))  address (xh number, zz varchar2(10)完成 给表student添加一列zz 是varchar2(10)类型,再从address中,将zz字段的数值取出来,对应的插入到表student新增的zz列中 

    alter table studnet add zz varchar2(10);
      declare
        xh1 number;
        zz1 varchar2(10);
        cursor  cursor1 is select xh,zz  from address;
      begin
        open cursor1;
        fetch cursor1 into xh1,zz1 ;
        while  cursor1%found loop
          update student  set zz=zz1 where xh = xh1;
        end loop;
        close cursor1;
      end;

    循环游标:只能进行select 不能进行update

    写法: 

    for  <record_index> in <cursor_name> loop 
       <executable statements>
    end loop;
    declare
      stu1  student%rowtype;
      cursor  mycursor  is select  * from student;
    begin
      for cur_2 in  mycursor loop
      dbms_output.put_line('学号是:'  || cur_2.sno || '学生名为:' || cur_2.sname ||'学生年龄为;' ||cur_2.sage);
      end loop;
    
    end

    在大量数据处理情况下:

    fetch cursor_name bulk collect into variable;
    --
    fetch cursor_name into variable --效率高、速度快

    ref游标

    创建ref游标变量两个步骤:

      声明ref游标类型

      声明ref游标类型的变量

    --用于声明ref游标类型的语法:
    type  <ref_cursor_name> is ref cursor
    [return  <return_type>];
    --打开游标 变量的语法
    open cursor_name for select_statement;

    例子:使用ref游标查询student(sno,sname)表中的姓名

      declare 
        type  refcur  is ref cursor;
        cursor2 refcur;
    
        tab varchar2(50);
        tab_name  varchar2(50);
        sno1  student.sno%type;
        sname1 student.sname%type;
      begin
        tab_name := '&tab';
        if  tab_name ='studnet'  then
          open cursor2 for select sno,sname form student;
          fetch cursor2 into sno1,sname1;
          while corsor2%found loop
            dbms_output.put_line('学号为:' || sno1 || '姓名为:' || sname1);
          end loop;
          close cursor2;
        else  
          dbms_output.put_line('输入为不正确的表名');           
        end if;
      end;

    显示游标和ref游标一起使用

    例:学生表student(xh number ,kc varchar2(10));  生成student2表(xh number ,kc varchar(50)) 要求对应于每个学生,求出他的总的 选课记录,把 每个学生的选课记录插入到student2表中,即将一位学生的所有记录 放入student2表中的kc中 

     1 declare 
     2     xh1  student.xh%type;
     3     kc1   varchar2(50) := ''; --保存对应学生的课程
     4     kc2   varchar2(50);
     5     
     6     cursor cursor1 is select  distinct(xh) from student;
     7     type  refcur  is  ref  cursor;
     8     cursor2  refcursor;
     9 
    10 begin 
    11     open  cursor1 ;
    12     fetch cursor1 into xh1;
    13     while cursor1%found loop
    14             kc1 := '';
    15             open cursor2 for select kc from student where xh = xh1;
    16             fetch cursor2 into kc2;
    17             while cursor2%found loop
    18                     kc1 := kc1 || kc2;
    19                     fetch cursor2 into kc2;
    20              end loop;
    21             close cursor2;
    22             insert  into student2 values(xh1,kc1);
    23             commit;
    24             fetch cursor1 into xh1;
    25     end loop;   
    26     close cursor1;
    27 end;                

    -----------------------------      触发器     ------------------------------------------------------------

    create [or replace] trigger  trigger_name
    after / before / instead of           -- after触发器的工作原理:先保存数据库数据的更新,再激活触发器
                                          --before触发器的工作原理:先激活触发器,再保存更新数据库数据
    [ insert]  [ [or] update [of column_list] ]  [ [or] delete]
    on table_or_view_name
    [referencing {old [as] old / new [as] new} ]
    [for each row]  --行级触发器,如果没有该行就是表级触发器
    [when  condition]
    pl/sql_block;
    
       --new   代表用户即将插入数据库中的某行记录的新表值
       --old   代表即将删除的该行数据记录得旧表值

    触发器中不能使用 :rollback、commit、create、 dorp、 alter、 savepoint等内容

    触发条件谓词:当插入数据时触发谓词inserting

                             当进行更新数据时的触发谓词updating

           当进行删除数据时的触发谓词deleting

    例1:当用户插入或更新 成绩表中的记录时候,就输出一个提示“触发器响应了”

    create  or replace trigger  trigger1
    before insert or update on 成绩表
    begin
            dbms_output.put_line('触发器响应了');
    end

    例2:当向学生表中插入数据时,需要控制学生学号不可以为负数 

    create  or replace trigger trigger2
            before  insert on student  
      for each row
      begin 
        if  now.sno <0   then 
          raise_application_error(-2001,'学号错误,不能插入表中');
        end ifend

     例3:当向学生表 中插入 数据时,需要控制学生学号 不能为负数,如果为负数,则将负数改为绝对值的正数插入 

    create or replace trigger trigger3 
    before insert on student 
    for each row
    begin 
      if  :now.no<0  then 
        now.sno  :=   -now.sno;
      end if;
    end;

    常用的系统变量 

    ora_client_ip_address     --返回客户端的ip地址
    ora_database_name         --返回当前 数据库名
    ora_login_user            --返回登录用户名
    ora_dict_obj_name         --返回ddl 操作所对应的数据库对象名
    ora_dict-obj_type         --返回ddl操作所对应的数据库对象类型

    instead  of触发器:修改视图中,非键值表中的列 定义在视图上,用来替换实际的操作语言

    例4:学生表(sno,sname,sage)

             住址表(sno,zname)

            视图(sno,sname,zname)更新视图 将学生名为kite的住址换成安徽

      create or replace trigger trigger4
      instead of  update  on view_stu_add  
      for each row
      declare 
             aa  number :=0;
       begin
           select  sno  into  aa  from student   where sname = old.sname;
            delete from  address    where   sno   =  aa;
              insert  into  address  values(aa,:new.zz);
       end;
       update view_stu_add  set  zname ='安徽' where sname = 'kite';

    例5:当用户对学生成绩表student(sno,sname,score)进行增删改的时候,将当时情况输出 出来,增加时,记录增加的信息,更新时,记录更新前、后的记录信息,删除的时候 ,记录删除的记录 

    create or replace trigger trigger5
      before  insert or update or  delete  on student
      for each row
      begin  
        if  inserting then 
          dbms_output.put_line('插入的学生 学号是:'|| new.sno || '姓名是:' || new.sname ||'成绩是 :'|| new.score);
        end if;
        if  updating   then
          dbms_output.put_line('原始学生的学生 学号是:'|| old.sno || ‘姓名是:’ || old.sname ||'成绩是 :'|| old.score);
          dbms_output.put_line('新的学生的学生 学号是:'|| new.sno || '姓名是:' || new.sname ||'成绩是 :'|| new.score);
        end if;
        if  deleting then 
          dbms_output.put_line('删除的学生 学号是:'|| old.sno || ‘姓名是:’ || old.sname ||'成绩是 :'|| old.score);
        end if;
      end; 

    --------------------------------     程序包    ---------------------------------------------------------------

    程序包 :是对于相关过程、函数、变量、游标和异常等对象的封装

    程序包的组成部分:包规范(包头)、包主体(包体)组成

    包头:公用类型的变量、常量、异常 、过程、函数等的 声明

    包体:私有类型的变量、常量、异常 、过程、函数等的 声明,以及包头内的过程、函数的实现。

    创建包头的语句: 

    create or replace package package_name  
      is/as
      public item declarations   --公有对象:在包的外部也可使用
      subprogram specification
      end  package_name;

    创建包体的语句: 

    create or replace package body package_name
    is/as
    private item declarations --私有对象:只能在包体之内使用,范围超出包体则不可再使用
    subprogram bodies
    begin
      initialization
    end package_name;

    程序包中的存储过程:

    例1: 两张表  student(sno,snme,sage)、address(sno,zz)

    create or replace package pack1
    is 
      aa int :=9; --公共变量,包外依然可访问应用
      procedure  insert_student(a1 in student%rowtype); --声明存储过程
      procedure uppdate_student(a2 in student%rowtype);--声明存储过程
    end pack1;
    create or replace package body pack1 is   bb int :=5; --私有变量 使用范围 包的内部   procedure insert_student(a1 in student%rowtype)   is   begin     insert into student(sno,sname,sage)     values(a1.sno,a1.sname,a1.sage);     commit;     dbms_output.put_line(pack1.bb);   end insert_student;   procedure update_student(a2 in student%rowtype) --根据传入参数的学号,修改学生名   is   begin     update student set sname = a2.sname where sno = a2.sno;     commit;   end update_student;
    end pack1;   execute dbms_output.put_line(pack1.aa); --可输出结果   execute dbms_output.put_line(pack1.bb);--不可输出结果

    包的使用:在pl/sql程序块中

    declare 
        a1 student%rowtype;
      begin 
        a1.sno :=8;
        a1.sname:='AA';
        a1.sage "=24;
        pack1.insert_studnet(a1);
      end;
    
    
      declare 
        a2 student%rowtype;
      begin 
        a2.sno :=8;
        a2.sname :='BB';
        a2.sage = 27;
        pack1.update_studnet(a2);
      end;

    程序包中的游标

           游标的定义分为游标规范和游标主体两部分

      在包规范中声明游标规范时必须使用return子句指定游标的返回类型

    return 子句指定的数据类型可以是:

      用%rowtype 属性引用表定义的记录类型;

      定义的记录类型,例如:type emprectyp is record( emp _id integer, salary real)来定义的

      不可以是number、varchar2、%type等类型

    程序包内,使用显示游标

    create or replace package pack2 is
        cursor mycursor return student%rowtype;
        procedure mycursor_use;
    end pack2;
    create or replace package body pack2 is 
      cursor mycursor  return studnet%rowtype  is select * from student;
      procedure mycursor_use
       is 
        stu_rec studnet%rowtype;
      begin
        open mycursor;
        fetch mycursor into stu_rec;
        while mycursor%found loop
          dbms_output.put_line( '学号是' || stu_rec.sno || ‘姓名是’ || stu_rec.sname || '年龄是' || stu_rec.sage);
          fetch mycursor into stu_rec;
        end loop;
        close mycursor;
      end mycursor_use;
    end pack2;
    
      exec pack2.mycursor_use; 

    程序包内,使用 ref 游标

    create or replace package pack3 is 
        type refcur is ref cursor;
         procedure mycursor_use;
    end pack3;
    
    create or replace package body pack3 is 
        procedure mycursor_use
        is 
            mycursor refcur;
            stu_rec student%rowtype;
        begin
            open mycursor for select * from student;
            fetch  mycursor into stu_rec;
            while mycursor%found loop
                     dbms_output.out_line('学号是:' || stu_rec.sno || '姓名是:'||stu_cur.sname);
                     fetch mycursor into stu_rec;
            end loop;
            close mycursor;
        end mycursor_use;
    end pack3;

    --执行
    execute pack3.mycursor_use;
  • 相关阅读:
    小心SQL SERVER 2014新特性——基数评估引起一些性能问题
    SQL SERVER使用ODBC 驱动建立的链接服务器调用存储过程时参数不能为NULL值
    Windows Server 2012 Recycle Bin corrupted
    SQL SERVER CHAR ( integer_expression )各版本返回值差异的案例
    SQL Server 2008 R2 升级到 Service Pack 3后Report Builder启动不了
    MySQL如何导出带日期格式的文件
    ORACLE TO_CHAR函数格式化数字的出现空格的原因
    Linux监控工具介绍系列——smem
    Linux命令学习总结:dos2unix
    Linux命令学习总结:hexdump
  • 原文地址:https://www.cnblogs.com/sun1997/p/13398626.html
Copyright © 2020-2023  润新知