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

时间:2024-07-04 23:03:32

一、游标

  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轻量版(三)——游标与异常处理

  游标的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轻量版(三)——游标与异常处理

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

    示例:

--打印员工信息
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;