• Oracle中的游标、事务处理、异常


    一 游标:游标(cursor)是一种PL/SQL控制结构:它可以命名一个工作区来存取该工作区的存储信息。可以非常方便的帮助我们从数据库中提取多行数据,然后可以对每一条数据进行单独处理。
    1)游标的四个属性:%found      查询语句(FETCH语句)返回记录
                              %notfound   查询语句(FETCH语句)无返回记录,用于循环退出条件
                              %isopen     光标已打开标记
                              %rowcount   FETCH已获取的记录数
    2)while和for语句访问游标
    3)定义带参数的游标,并访问
    4)定义隐式游标,并访问
              隐式游标属性
       SQL%FOUND    : SQL语句返回有记录
       SQL%NOTFOUND : SQL语句返回无记录
       SQL%ROWCOUNT : SQL语句记录总数


    -----------------------------------------
    eg1:while访问
    declare
        v_id    tbl_student.studentid%type;
        v_name tbl_student.studentname%type;
        cursor c1 is select studentid, studentname from tbl_student where rownum <= 20;
        
    begin
        open c1;--打开游标
            fetch c1 into v_id, v_name; --提取游标
            while c1%found loop --使用了%found属性
                dbms_output.put_line(v_id || '    ' || v_name);
                fetch c1 into v_id, v_name;
            end loop;
        close c1;--关闭游标
    end;
    ---------------------------------------------
    eg2:for访问
    declare
        cursor c1 is select studentid, studentname from tbl_student where rownum <= 20;    
    begin    --使用for时,游标不用打开、不用关闭、不用提取。直接用a1访问表的字段。a1不是游标,可以认为是指向游标的指针。
        for a1 in c1 loop
            dbms_output.put_line(a1.studentid || '    ' || a1.studentname);
        end loop;        
    end;
    -----------------------------------------------
    eg3:for访问带参数的游标
    declare    
        cursor c1(v_num number, v_sex number) is --带参数的游标
        select studentid, studentname, sex from tbl_student where (rownum <= v_num) and (sex = v_sex);    
    begin    
        for a1 in c1(10, 2) loop --定义带参数的游标
            dbms_output.put_line(a1.studentid || '    ' || a1.studentname || '    ' || a1.sex);
        end loop;
    end;
    ------------------------------------------------------
    eg4:while访问带参数的游标
    declare
        v_id    tbl_student.studentid%type;
        v_name tbl_student.studentname%type;
        v_sex   tbl_student.sex%type;
        cursor c1(v_num number, v_sex number) is 
        select studentid, studentname, sex from tbl_student where (rownum <= v_num) and (sex = v_sex);    
    begin
        open c1(30, 1);
            fetch c1 into v_id, v_name, v_sex; --提取游标
            while c1%found loop --使用了%found属性
                dbms_output.put_line(v_id || '    ' || v_name || '    ' || v_sex);
                fetch c1 into v_id, v_name, v_sex;
            end loop;        
        close c1;    
    end;
    --------------------------------------------------------
    eg5:for访问隐式游标
    declare    
    begin    
        for a1 in (select studentid, studentname, sex from tbl_student where rownum <= 20) loop
            dbms_output.put_line(a1.studentid || '    ' || a1.studentname || '    ' || a1.sex);
        end loop; 
    end;

    二 异常: 在PL/SQL中一个警告或错误的情形都被叫做异常。我们可以编写一段叫异常处理器的独立程序来控制出发异常。当一个异常被触发的时候,当前的块就会转到异常处理部分。

    异常类型:
    系统预定义的异常: 是由PL/SQL运行过程中,系统自动产生的信息。
    用户定义异常:     是用户根据需要,自己定义使用的异常,执行时由用户自己引起。

    预定义的异常类型:
    CURSOR_ALREADY_OPEN    :    光标已经存在
    VALUE_ERROR            :    值错误
    NO_DATA_FOUND          :    没有找到数据
    INVALID_NUMBER         :    无效数值
    TOO_MANY_ROWS          :    返回太多的行
    ZERO_DIVIDE            :    被0除
    INVALID_CURSOR         :    无效光标
    --------------------------------------------------------
    eg1:系统预定义异常:NO_DATA_FOUND使用示例。
    declare
        v_studentid    tbl_student.studentid%type;
    begin
        select studentid into v_studentid from tbl_student where studentname='dddddd';    
    exception
        when NO_DATA_FOUND then
            dbms_output.put_line('exception:no_data_found');
        when others then
            dbms_output.put_line('error!');
        
    end;

    自定义异常说明:
    用户定义的异常必须在DECLARE段中说明,在Begin段中用RAISE引起,在EXCEPTION段中使用。
    -----------------------------------------------------------
    eg1:用户自定义异常
    declare
        my_exception    exception;--用户自定义异常
        v_num           number := 0;
    begin
        select count(*) into v_num from tbl_student where studentname='yyyy';    
        if v_num = 0 then --如果不存在符合条件的记录,引发异常
            raise my_exception; 
        else
            dbms_output.put_line('存在这个姓名的学生。'); --如果触发了异常就不会执行此语句
        end if;    
    exception
        when my_exception then
            dbms_output.put_line('该学生不存在。');
        when others then
            dbms_output.put_line('error!'); 
    end;
    三 事务处理

    事务概念:
    数据库中的重要机制,确保数据完整性和并发处理的能力,它将一条或者一组sql语句当成一个逻辑上的单元,用于保障这些语句要么都成功,要么都失败。
    事务的特性:
    1)原子性:事务中的操作,要么全做成,要么都不做,事务是不可拆分的
    2)一致性:单独运行的事务,必须保证保持数据库的一致状态
    3)隔离性:多个并发事务之间不能相互干扰
    4)永久性:一旦事务成功完成(Commit),它对数据库的操作是持久的

    开始于第一个执行的语句:DML。
    结束于以下几种情况:
    1)显示执行commit/rollback;
    2)执行于DDL语句或者DCL时候事物会自动提交,再rollback提交不回去了
    3)正常断开的时候:
                     如exit ,transaction会自动提交
                     非正常断开的时候,如直接关闭transaction会自动回滚。
    -----------------------------------------------------
    eg1:事务处理示例
    declare    
    begin
        update tbl_accountinfo set name = 'lucy' where id = 2;
        savepoint sp1; --定义一个事务点
        delete from tbl_accountinfo where id = 2;
        rollback to savepoint sp1; --回滚到事务点sp1。
        commit;   --提交。只执行了修改,没执行删除。事务回滚了。
        
    exception
        
        when others then
            dbms_output.put_line('error!');   
        
    end;
    ---------------------------------------------------------
    eg2:
    declare
        v_i     scott.emp.ename%type;
    begin
        update scott.emp set ename = 'macle3' where empno = 7369;
        savepoint sp1;
        select ename into v_i from scott.emp where empno=1114465461; --没有符合要求的记录
        
        if sql%notfound then --如果此事务不作if判断,依然会执行下面的rollback,commit。上面的select语句不会报错。
            dbms_output.put_line('data_not_found!'); 
        else 
            dbms_output.put_line('ok!');   
        end if; 
        rollback to savepoint sp1;
        commit;
    exception    
        when no_data_found then
            dbms_output.put_line('data_not_found!');   
        
    end;
    -----------------------------------------------------------------
    eg3:
    declare
        v_i     scott.emp.ename%type;
    begin
        update scott.emp set ename = 'macle3' where empno = 7369;
        savepoint sp1;
        select ename into v_i from scott.emp where empno=1114465461;--此时会跳到异常处理。事务全部执行不成功。
            
        commit;
    exception    
        when no_data_found then
            dbms_output.put_line('data_not_found!');   
        
    end;

  • 相关阅读:
    「转」xtrabackup新版详细说明
    微博MySQL优化之路--dockone微信群分享
    分享的好处
    DBA的技能图谱
    高效运维--数据库坐而论道活动
    MySQL的诡异同步问题-重复执行一条relay-log
    把信送给加西亚读后感
    一次由于字符集问题引发的MySQL主从同步不一致问题追查
    nginx解决浏览器跨域问题
    kubernetes之pod调度
  • 原文地址:https://www.cnblogs.com/xinzhuangzi/p/4100405.html
Copyright © 2020-2023  润新知