现在的位置: 首页 > 综合 > 正文

oracle学习大全–光标设计(Cursor)

2013年10月12日 ⁄ 综合 ⁄ 共 4012字 ⁄ 字号 评论关闭

1、什么是光标?在PL/SQL中,当查询语句执行结果超过一行时,为处理每一行,必须定义一个cursor,叫光标。


2、光标使用方法:
(1) 定义光标:
语法:光标名 is select 语句;

(2) 打开光标:
语法:open 光标名;

(3) 取数据:
语法:Fetch 光标名 into 变量;

(4) 光标下移:使用loop循环

(5) 关闭光标:close 光标名;

例:
Declare
        v1 emp.empno%type;
        v2 emp.ename%type;
        v3 emp.sal%type;
        cursor c is select empno,ename,sal from emp;
     Begin
         open c;
         loop
         fetch  c into v1,v2,v3;
         if v3<3000 then Begin
                           update emp set sal=sal+100
                           where empno=v1;
                    dbms_output.put_line('员工'||v2||'工资已经更新!');
                                    End;
         end if;
         exit when c%NOTFOUND;
         end loop;
         close c;
     End;
/

-- //要求从emp表中取出按用户输入要求的前几位工资最高的人员及其工资放入topsalary表中:
-- // 我的方法:
SQL>create table topsalary (
 name varchar2(20),
 sal number(7,2));
 
SQL>Declare
  vcount number(7) := &n;
  i number(7) :=0;
        vname emp.ename%type;
        vsal emp.sal%type;
        cursor c is select ename,sal from emp order by nvl(sal,0) desc; --// 使用nvl函数防止工资出现空值的情况,老师补充
     Begin
      delete topsalary;  -- // 先清空topsalary表
         open c;
        
         for i in 1 .. vcount loop
         fetch  c into vname, vsal;
        
         insert into topsalary values(vname,vsal);
        
         end loop;
         close c;
     End;
 
--//教师的方法
Declare
    i number(3) :=&i;
    j number(3) :=0;
   cursor c is select ename,sal from emp order by nvl(sal,0) desc;
   v1 emp.ename%type;
   v2 emp.sal%type;
Begin
   open c;
   loop
   j := j+1;
   fetch c into v1,v2;
   insert into topsalary  values(v1,v2);
   exit when j=i;
   end loop;
   close c;
End;

3. 光标属性:  每一个光标有四种属性
%FOUND         查询语句(FETCH语句)返回记录
%NOTFOUND      查询语句(FETCH语句)无返回记录,用于循环退出条件
%ROWCOUNT     FETCH已获取的记录数
%ISOPEN        光标已打开标记

例:
Declare
        v1 emp.empno%type;
        v2 emp.ename%type;
        v3 emp.sal%type;
        cursor c is select empno,ename,sal from emp;
     Begin
         open c;
         loop
         fetch  c into v1,v2,v3;
         if v3<3000 then Begin
                           update emp set sal=sal+100
                           where empno=v1;
                    dbms_output.put_line('员工'||v2||'工资已经更新!');
                                    End;
         end if;
         exit when c%NOTFOUND;
         end loop;
         dbms_output.put_line('光标处理的行数:'||C%ROWCOUNT);
         close c;
     End;
    
4. 隐式光标处理: 隐式光标是指在处理SQL时,不需定义光标,所使用的SQL语句包括:INSERT ,UPDATE,DELETE子句。

隐式光标属性:       SQL%FOUND        SQL%NOTFOUND              SQL%ROWCOUNT

隐式光标的使用:
Declare
 v_empno emp.empno%type:=&empno;
Begin
 delete from emp where empno=v_empno;
 if SQL%NOTFOUND then
  dbms_output.put_line('你的删除失败,数据库无此人:'||v_empno);
 end if;
End;

[例外处理Exception]
Declare
       v_empno emp.empno%type :=&empno;
       v_ename emp.ename%type;
       v_sal emp.sal%type;
Begin
      select sal,ename into v_sal,v_ename from emp
      where empno=v_empno;
       if v_sal<2000 then Begin
                  update emp set sal=sal+100
                  where empno=v_empno;
        dbms_output.put_line('员工'||v_ename||'工资已经修改!');
                                       End;
        elsif v_sal<2500 then Begin
                  update emp set sal=sal+50
                  where empno=v_empno;
        dbms_output.put_line('员工'||v_ename||'工资已经修改!');
                                       End;
        elsif v_sal<3000 then Begin
                  update emp set sal=sal+10
                  where empno=v_empno;
        dbms_output.put_line('员工'||v_ename||'工资已经修改!');
                                       End;
        else dbms_output.put_line('员工'||v_ename||'的工资已经超过规定值,不予更新!');
        End if;
Exception   -- // 例外处理
 when NO_DATA_FOUND then dbms_output.put_line('数据库中没有编码为'||v_empno||'的员工。');
 when TOO_MANY_ROWS then
  dbms_output.put_line('你的查询语句返回结果出现多行,请定义光标后重试!');
 when OTHERS then
  dbms_output.put_line('你的程序是错误的,请仔细检查后重试!');
End;

[用户定义的例外]
(1)在Declare段定义
(2)在Begin段中用Raise引起。
(3)在Exception段中使用。

Declare
       v_empno emp.empno%type :=&empno;
       no_result exception;
Begin
 delete from emp where empno = v_empno;
 if SQL%NOTFOUND then raise no_result;
 end if;
 
Exception   -- // 例外处理
 when NO_DATA_FOUND then dbms_output.put_line('数据库中没有编码为'||v_empno||'的员工。');
 when NO_RESULT then dbms_output.put_line('数据库中没有编码为'||v_empno||'的员工。');
 when TOO_MANY_ROWS then
  dbms_output.put_line('你的查询语句返回结果出现多行,请定义光标后重试!');
 when OTHERS then
  dbms_output.put_line('你的程序是错误的,请仔细检查后重试!');
End;

抱歉!评论已关闭.