PL/SQL编程(下)

游标

游标的操作

  1. 步骤
  2. 定义游标
定义游标
语法
    CURSOR cursor_name IS select_statement ;
说明
游标必须在PL/SQL块的声明部分进行定义;
游标定义时可以引用PL/SQL变量,但变量必须在游标定义之前定义;
定义游标时并没有生成数据,只是将定义信息保存到数据字典中;
游标定义后,可以使用cursor_name%ROWTYPE定义游标类型变量。
  1. 打开游标
打开游标
语法
   OPEN cursor_name; 
说明
检查变量的值
执行游标定义时对应的SELECT语句,将查询结果检索到工作区中。
游标指针指向第一个元组。
一旦游标打开,就无法再次打开,除非先关闭。
如果游标定义中的变量值发生变化,则只能在下次打开游标时才起作用。
  1. 检索游标
检索游标
语法格式
   FETCH cursor_name INTO variable_list|record_variable; 
说明
在使用FETCH语句之前必须先打开游标
对游标第一次使用FETCH语句时,游标指针指向第一条记录,因此操作的对象是第一条记录,使用后,游标指针指向下一条记录。
游标指针只能向下移动,不能回退。
INTO子句中的变量个数、顺序、数据类型必须与工作区中每行记录的字段数、顺序以及数据类型一一对应。
  1. 关闭游标
关闭游标
语法格式
    CLOSE cursor_name; 
说明
游标所对应的内存工作区变为无效,释放与游标相关的系统资源

声明一个检索emp表中雇员信息的游标,然后打开游标,并指定检索职务是’MANAGER’的雇员信息,接着使用 fetch…into语句和while循环读取游标中的所有雇员信息,最后输出读取的雇员信息。

DECLARE
Cursor cur_emp(var_job in varchar2:=‘SALESMAN’)
Is select empno,ename,sal
From emp
Where job=var_job;
Type record_emp is record
(var_empno emp.empno%type,
var_ename emp.ename%type,
var_sal emp.sal%type);
Emp_row record_emp;
BEGIN
  open cur_emp(‘MANAGER’);
Fetch cur_emp into emp_row;
While cur_emp%found loop
Dbms_output.put_line(emp_row.var_ename||’的编号是’||
emp_row.var_empno||’,工资是’||emp_row.var_sal);
Fetch cur_emp into emp_row;                                
  END LOOP; 
  CLOSE c_emp;
END; 

显式游标的属性

%ISOPEN
布尔型。如果游标已经打开,返回TRUE,否则为FALSE。
%FOUND
布尔型,如果最近一次使用FETCH语句,有返回结果则为TRUE,否则为FALSE;
%NOTFOUND
布尔型,如果最近一次使用FETCH语句,没有返回结果则为TRUE,否则为FALSE;
%ROWCOUNT
数值型,返回到目前为止从游标缓冲区检索的元组数。
%BULK_ROWCOUNT(i)
数值型,用于取得FORALL语句执行批绑定操作时第i个元素所影响的行数。
声明一个游标,用于检索指定员工编号的雇员信息,然后使用游标的%found属性来判断是否检索到指定员工编号的雇员信息。
DECLARE
Var_ename varchar2(50);
Var_job varchar2(50);
Cursor cur_emp
Is select ename,job
From emp
Where empno=7499;
BEGIN
  open cur_emp;
Fetch cur_emp into var_ename,var_job;
If cur_emp%found then
Dbms_output.put_line(‘编号是7499的雇员名称为:’||var_ename||’,
职务是:’||var_job);
Else
Dbms_output.put_line(‘无数据记录’);
End if;
END; 

** 隐式游标**

概念
所有的SQL语句都有一个执行的缓冲区,隐式游标就是指向该缓冲区的指针,由系统隐含地打开、处理和关闭。隐式游标又称为SQL游标。
隐式游标主要用于处理INSERT、UPDATE,DELETE以及单行的SELECT…INTO语句,没有OPEN,FETCH,CLOSE等操作命令。

修改员工号为1000的员工工资,将其工资增加100。如果该员工不存在,则向emp表中插入一个员工号为1000,工资为1600的员工。

 BEGIN
    UPDATE emp SET sal=sal+100 WHERE empno=1000;
    IF SQL%NOTFOUND THEN
      INSERT INTO emp(empno,sal) VALUES(1000,1600);
    END IF;
  END;
或
  BEGIN
    UPDATE emp SET sal=sal+100 WHERE empno=1000;
    IF SQL%ROWCOUNT=0 THEN
      INSERT INTO emp(empno,sal) VALUES(1000,1600);
    END IF;
  END;

通过for语句循环游标

语法格式:
For var_auto_record in cur_name loop
Plsqlsentence;
End loop;
例:使用显式游标和for语句检索出部门编号是30
的雇员信息并输出。

SQL>set serveroutput on
SQL>declare
    cursor cur_emp is
    select * from emp
    where deptno=30;
    begin
    for emp_record in cur_emp
    loop
      dbms_output.put(‘雇员编号:’||emp_record.empno);
      dbms_output.put(‘:雇员名称:’||emp_record.ename);
      dbms_output.put_line(‘:雇员职务:’||emp_record.job);
     end loop;
    end;
    /
例:使用隐式游标和for语句检索出职务是销售员
的雇员信息并输出。

SQL>set serveroutput on
SQL>begin
    for emp_record in(select empno,ename,sal from emp
    where job=‘SALESMAN’)
    loop
      dbms_output.put(‘雇员编号:’||emp_record.empno);
      dbms_output.put(‘:雇员名称:’||emp_record.ename);
      dbms_output.put_line(‘:雇员工资:’||emp_record.sal);
     end loop;
    end;
    /

预定义异常

例:使用select into语句检索emp表中部门编号为10的雇员记录信息,
然后使用“too_many_rows”预定义异常捕获错误信息并输出。

DECLARE
  Var_empno number;
  Var_ename varchar2(50);
Begin
  Select empno,ename into var_empno,var_ename
  From emp
  Where deptno=10;
  If sql%found then
  Dbms_output.put_line(‘雇员编号:’||var_empno||’;雇员名称’
||var_ename);
 End if;
Exception
 When too_many_rows then
 Dbms_output.put_line(‘返回记录超过一行’);
 When no_data_found then
 Dbms_output.put_line(‘无数据记录’);
End;

自定义异常

声明一个异常名称
e_integrity EXCEPTION;
将异常与一个Oracle错误号相绑定
PRAGMA EXCEPTION-INIT(e_integrity.-2291)
示例

DECLARE
  e_deptno_fk EXCEPTION;
  PRAGMA EXCEPTION_INIT(e_deptno_fk,-2292);
BEGIN
……
EXCEPTION
……
END;

异常处理过程

异常处理分3个步骤进行:
在声明部分为错误定义异常,包括非预定义异常和用户定义异常。
在执行过程中当错误产生时抛出与错误对应的异常。
在异常处理部分通过异常处理器捕获异常,并进行异常处理。

异常的捕获与处理

例如,查询名为SMITH的员工工资,如果该员工不存在,则输出“There is not such an employee!”;如果存在多个同名的员工,则输出其员工号和工资。

DECLARE
  v_sal emp.sal%type;
BEGIN
  SELECT sal INTO v_sal FROM emp WHERE ename='SMITH';
  DBMS_OUTPUT.PUT_LINE(v_sal);
EXCEPTION
  WHEN NO_DATA_FOUND THEN 
    DBMS_OUTPUT.PUT_LINE('There is not such an emplyee!');
  WHEN TOO_MANY_ROWS THEN
    FOR v_emp IN (SELECT * FROM emp WHERE ename='SMITH')    
    LOOP
       DBMS_OUTPUT.PUT_LINE(v_emp.empno||' '||v_emp.sal);
    END LOOP;
END;
发布了36 篇原创文章 · 获赞 26 · 访问量 7581

猜你喜欢

转载自blog.csdn.net/weixin_43566977/article/details/103657497
今日推荐