PL/SQL轻量版(三)——游标与异常处理

摘要:
通过光标,PL/SQL可以控制上下文区域以及处理语句时上下文区域中发生的情况。隐式游标的定义、打开、取值和关闭等操作由ORACLE系统自动完成,无需用户处理。在隐式游标工作区中,存储的数据是新处理的SQL语句中包含的数据,与用户定义的显示游标无关。此异常的处理不需要在程序中定义。它由ORACLE自动抛出。

一、游标

  1.概念

    游标是一个 指向上下文的句柄( handle) 或指针。通过游标,PL/SQL 可以控制上下文区和处理语句时上下文区会发生些什么事情。

  2.游标处理

    处理显式游标

    主要包含以下四个步骤:

      1.定义游标

CURSOR cursor_name[(parameter[, parameter]…)] IS select_statement;
游标参数只能为输入参数,其格式为:
parameter_name [IN] datatype [{:= | DEFAULT} expression]
在指定数据类型时,不能使用长度约束。如 NUMBER(4)、CHAR(10) 等都是错误的。

      2.打开游标

--就是执行游标所对应的 SELECT 语句,将其查询结果放入工作区,并且指针指向工作区的首部,标识游标结果集合。
OPEN cursor_name[([parameter =>] value[, [parameter =>] value]…)];
--参数支持位置表示法和名称表示法

      3.提取游标数据(放入变量或记录类型)

FETCH cursor_name INTO {variable_list | record_variable };

      4.关闭游标

CLOSE cursor_name;

     游标相关属性:

%FOUND 布尔型属性,当最近一次读记录时成功返回,则值为 TRUE;
%NOTFOUND 布尔型属性,与%FOUND 相反;
%ISOPEN 布尔型属性,当游标已打开时返回 TRUE;
%ROWCOUNT 数字型属性,返回已从游标中读取的记录数。

   简单示例:——WHILE循环

--打印80部门所有员工的工资
DECLARE
  v_sal employees.salary%type;
  --1.定义游标
  CURSOR emp_sal_cursor IS SELECT salary FROM employees WHERE department_id = 80;
BEGIN
  --2.打开游标
  OPEN emp_sal_cursor;
  --3.提取游标数据(取出当前游标的指向的数据)
  FETCH emp_sal_cursor INTO v_sal;
  --循环操作found类似迭代器的hasNext()
  WHILE emp_sal_cursor%found LOOP
        dbms_output.put_line('salary:'||v_sal);
        --再取一次
        FETCH emp_sal_cursor INTO v_sal;
        END LOOP;
   --4.关闭游标
   CLOSE emp_sal_cursor;
END;

  //当然可以使用多个变量甚至可以使用记录类型进行操作!

 带参数的示例如下:

  PL/SQL轻量版(三)——游标与异常处理第1张

  游标的FOR循环:   

  PL/SQL 语言提供了 游标 FOR 循环语句,自动执行游标的 OPEN 、FETCH 、CLOSE 语句和 循环 语句的功能
当进入循环时,游标 FOR 循环语句 自动 打开游标,并提取第一行游标数据,当程序处理完 当前所提取的数
据而进入下一次循环时,游标 FOR 循环语句自动提取下一行数据供程序处理,当提取完结果集合中的所有
数据行后结束循环,并自动关闭游标。

FOR index_variable IN cursor_name[value[, value]…] LOOP
-- 游标数据处理代码
END LOOP;
index_variable 为游标 FOR 循环语句隐含声明的索引变量,该变量为 记录变量,其 结构与游标查询语句
返回的结构集合的结构相同。在程序中可以通过引用该索引记录变量元素来读取所提取的游标数据,
index_variable 中各元素的名称与游标查询语句选择列表中所制定的列名相同。 如果在游标查询语句的选择
列表中存在计算列,则必须为这些计算列指定别名后才能通过游标 FOR  循环语句中的索引变量来访问这些
列数据

  示例:

--打印80部门所有员工的工资
DECLARE
  v_sal employees.salary%type;
  --1.定义游标
  CURSOR emp_sal_cursor IS SELECT salary,employee_id FROM employees WHERE department_id = 80;
BEGIN
  FOR c IN emp_sal_cursor LOOP
      dbms_output.put_line('salary:'||c.salary||',employee_id:'||c.employee_id);
  END LOOP;
END;

    处理隐式游标

  显式游标主要是用于对查询语句的处理,尤其是在查询结果为多条记录的情况下;而对于非查询语句,如修改、删除操作,则由 ORACLE 系统自动地为这些操作设置游标并创建其工作区,这些 由系统隐含创建的游标称为隐式游标, 隐式游标的名字为 SQL,这是由 ORACLE 系统定义的。对于隐式游标的操作,如定义、打开、取值及关闭操作,都由 ORACLE 系统自动地完成,无需用户进行处理。 用户只能通过隐式游标的相关属性,来完成相应的操作。在隐式游标的工作区中,所存放的数据是与用户自定义的显示游标无关的、最新处理的一条 SQL 语句所包含的数据。

SQL%

    游标属性:

SQL%FOUND 布尔型属性,当最近一次读记录时成功返回,则值为 TRUE;
SQL%NOTFOUND 布尔型属性,与%FOUND 相反;
SQL %ROWCOUNT 数字型属性, 返回已从游标中读取得记录数;
SQL %ISOPEN 布尔型属性, 取值总是 FALSE。SQL 命令执行完毕立即关闭隐式游标

   示例:

--打印员工信息
DECLARE
  v_sal employees.last_name%type;
  -- &v_id表示v_id将由外部输入
  v_id employees.employee_id%type := &v_id;
BEGIN
  UPDATE employees
  SET salary = salary*1.2
  WHERE employee_id = v_id;
  
  IF SQL%NOTFOUND THEN
     dbms_output.put_line('查无此人!');
  END IF;
END;

  更多游标相关,参考:https://www.cnblogs.com/xcre/archive/2012/03/28/2420597.html

 二、异常处理

  主要分为三类异常:

    1. 预定义 ( Predefined )错误

      ORACLE 预定义的异常情况大约有 24 个。对这种异常情况的处理,无需在程序中定义,由 由 ORACLE 自动将其引发。

    2.非预定义 ( Predefined )错误

      即其他标准的 ORACLE 错误。对这种异常情况的处理,需要用户在程序中定义,然后由 ORACLE 自动将其引发。

    3.用户定义(User_define) 错误

      程序执行过程中,出现编程人员认为的非正常情况。对这种异常情况的处理, 需要 用户在程序中定义,然后显式地在程序中将其引发。

    1.预定义异常处理

      主要预定义异常如下:

      PL/SQL轻量版(三)——游标与异常处理第2张

       PL/SQL轻量版(三)——游标与异常处理第3张

    示例:

--打印员工信息
DECLARE
  v_sal employees.salary%type;
  v_id employees.employee_id%type:=&v_id;
BEGIN
  SELECT salary INTO v_sal FROM employees WHERE employee_id = v_id;
  dbms_output.put_line('salary:'||v_sal);
EXCEPTION
  WHEN NO_DATA_FOUND THEN
       dbms_output.put_line('找不到数据!');
  WHEN OTHERS THEN
       dbms_output.put_line('其他异常!');
END;

    2.非预定义异常处理

    三步走:

       定义异常情况

       与标准的 ORACLE  错误联系起来(也就是说这个错误Oracle有自己的错误代码,但是不在上表中出现),使用 PRAGMA EXCEPTION_INIT 

          PRAGMA EXCEPTION_INIT(< 异常情况>, < 错误代码>)

       做出相应的处理

    示例:

DECLARE
  --定义异常
  e_del EXCEPTION;
  --关联异常
  PRAGMA EXCEPTION_INIT(e_del,-2292);
BEGIN
  DELETE FROM departments WHERE department_id = 10;
EXCEPTION
  WHEN e_del THEN
       dbms_output.put_line('无法删除包含外键的数据');
END;

    3.用户自定义异常

    需要使用RAISE显式触发异常,并且自定义异常的异常代码必须是–20,000 到 –20,999 之间的参数

    三步走:

      定义异常情况

       RAISE < 异常情况>

      做出相应的处理

  示例:

DECLARE
  --定义异常
  e_sal EXCEPTION;
  v_sal employees.salary%type;
BEGIN
  SELECT salary INTO v_sal FROM employees WHERE employee_id = 100;
  IF v_sal < 30000 THEN
     RAISE e_sal;
  END IF;
EXCEPTION
  WHEN e_sal THEN
       dbms_output.put_line('工资太低!');
END;

免责声明:文章转载自《PL/SQL轻量版(三)——游标与异常处理》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇CentOS+Nginx+PHP+Mysql 服务器配置神奇的position:sticky下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

oracle中游标的使用

oracle中的游标,游标的概念与作用,游标的分类,游标的使用。 一,游标的概念与作用    摘自百度百科:游标(Cursor)是处理数据的一种方法,为了查看或者处理结果集中的数据,游标提供了在结果集中一次一行或者多行前进或向后浏览数据的能力。可以把游标当作一个指针,它可以指定结果中的任何位置,然后允许用户对指定位置的数据进行处理。游标实际上是一种能从包括...

sqlserver 表循环-游标、表变量、临时表

SQL Server遍历表的几种方法 阅读目录 使用游标 使用表变量 使用临时表 在数据库开发过程中,我们经常会碰到要遍历数据表的情形,一提到遍历表,我们第一印象可能就想到使用游标,使用游标虽然直观易懂,但是它不符合面向集合操作的原则,而且性能也比面向集合低。当然,从面向集合操作的角度出发,也有两种方法可以进行遍历表的操作,总结起来,遍历表有下面...

MYSQL数据库基础篇

MySQL基础入门 一、数据库1 数据库概念(了解) 1.1 什么是数据库 数据库就是用来存储和管理数据的仓库! 数据库存储数据的优先: l  可存储大量数据; l  方便检索; l  保持数据的一致性、完整性; l  安全,可共享; l  通过组合分析,可产生新数据。 数据库具有原子性,数据不可再分割! 1.2 数据库的发展历程 l  没有数据库,使用...

MSIL实用指南-生成异常处理

本篇讲解怎么生成异常。C# 异常处理时建立在四个关键词之上的:try、catch、finally 和 throw。 一、异常的抛出抛出异常在C#语言中要使用throw关键字,使用方法是throw <一个异常对象>;和throw; 1、抛出异常抛出异常的指令是Throw,它对应的C#使用语句是throw new <异常类型>; 它的使...

redis Lua学习与坑

1.在写lua脚本往redis中添加zadd 有序集合的时候一直报 "value isnotavalid float"的错误,经过查询相关资料,最后发现,是顺序写反了。 相关代码 --[错误代码] redis.call('zadd',@TimeOrderKey,objRecord.ActivityID,@TimeScore);--[应该时间在前,value...

SQLServer 的存储过程与java交互

一、   存储过程简介 Sql Server的存储过程是一个被命名的存储在服务器上的Transacation-Sql语句集合,是封装重复性工作的一种方法,它支持用户声明的变量、条件执行和其他强大的编程功能。 存储过程相对于其他的数据库访问方法有以下的优点:    (1)重复使用。存储过程可以重复使用,从而可以减少数据库开发人员的工作量。     (2)...