游标-----内存中的一块区域,存放的是select的结果 
    
    游标用来处理从数据库中检索的多行记录(使用SELECT语句)。利用游标,程序可以逐个地处理和遍历一次检索返回的整个记录集。 
    为了处理SQL语句,Oracle将在内存中分配一个区域,这就是上下文区。这个区包含了已经处理完的行数、指向被分析语句的指针,游标就是指向上下文区句柄或指针。

缺点:游标使用时会对行加锁,可能会影响其他业务的正常进行。 
       而且,数据量大时其效率也较低。因为游标其实是相当于把磁盘数据整体放入了内存中,如果游标数据量大会造成内存不足,也有可能导致cpu高,所以,在数据量小时才使用游标。

优点:相当于程序中的FOR循环处理。一条一条的处理你读取的记录内容。 
       数据存放在内存中,数据量少的时候速度比较快。

一、显示游标 
    显示游标被用于处理返回多行数据的SELECT 语句,游标名通过CURSOR….IS 语句显示地赋给SELECT 语句。 
     在PL/SQL中处理显示游标所必需的四个步骤: 
     1)声明游标;CURSOR cursor_name IS select_statement 
     2)为查询打开游标;OPEN cursor_name 
     3)取得结果放入PL/SQL变量中; 
            FETCH cursor_name INTO list_of_variables; 
            FETCH cursor_name INTO PL/SQL_record; 
     4)关闭游标。CLOSE cursor_name 
     注意:在声明游标时,select_statement不能包含INTO子句。当使用显示游标时,INTO子句是FETCH语句的一部分。 
   
二、隐式游标 
     所有的隐式游标都被假设为只返回一条记录。 
     使用隐式游标时,用户无需进行声明、打开及关闭。PL/SQL隐含地打开、处理,然后关掉游标。 
     例如: 
     SELECT studentNo,studentName INTO curStudentNo,curStudentName 
     FROM StudentRecord  WHERE name=’gg’; 
     上述游标自动打开,并把相关值赋给对应变量,然后关闭。执行完后,PL/SQL变量curStudentNo,curStudentName中已经有了值。 
   
     单条sql语句所产生的结果集合 
     用关键字SQL表示隐式游标 
     4个属性 %rowcount  影响的记录的行数  整数 
             %found     影响到了记录  true 
             %notfound  没有影响到记录  true 
             %isopen    是否打开  布尔值 永远是false 
     多条sql语句 隐式游标SQL永远指的是最后一条sql语句的结果 
     主要使用在update 和 delete语句上 
     
三、常见游标实例     
(1)for循环游标 
SQL> set timing on 
SQL> set serverout on 
SQL> set pagesize 1000 
SQL> set linesize 400 
SQL> declare 
        cursor c1 is select id,ins_time,random_string from mytest where random_id=50;  ---定义游标 
        c1cur c1%rowtype;       ---定义一个游标变量 
     begin 
        for c1cur in c1 loop    ---for循环 
          dbms_output.put_line(c1cur.id||':'||c1cur.ins_time||'-'||c1cur.random_string); 
        end loop; 
     end; 
     / 
113:2015-12-23 16:39:41-1TP6AU8U5JJ1O16FIUSZ 
176:2015-12-23 16:40:44-N77Y47YGZQJH2ONG504R 
187:2015-12-23 16:40:55-PIQG1HNPM6EVFZXD8N7G

PL/SQL procedure successfully completed. 
Elapsed: 00:00:00.02

(2) fetch游标    --使用的时候 必须要明确的打开和关闭 
      declare 
        cursor c1 is select id,ins_time,random_id,random_string from mytest where random_id=50;  ---定义显示游标 
        c1cur c1%rowtype;       ---定义一个游标变量 
      begin 
         open c1;  --打开游标 
         loop 
            fetch c1 into c1cur;     ---取一行数据到游标变量      
            exit when c1%notfound;   ---判断是否取到了值 
            dbms_output.put_line(c1cur.id||':'||c1cur.ins_time||'-'||c1cur.random_string);           
         end loop; 
         close c1;   ---关闭游标 
      end; 
      / 
113:2015-12-23 16:39:41-1TP6AU8U5JJ1O16FIUSZ 
176:2015-12-23 16:40:44-N77Y47YGZQJH2ONG504R 
187:2015-12-23 16:40:55-PIQG1HNPM6EVFZXD8N7G

PL/SQL procedure successfully completed. 
Elapsed: 00:00:00.02

(3)参数游标(以下都利用scott自带的几张表测试) 
SQL> declare 
       cursor c1 is select deptno from dept; 
       cursor c2(pno number,pjob varchar2) is select * from emp where deptno=pno and job=pjob; --只能指定类型,不能指定长度 
       c1cur c1%rowtype; 
       c2cur c2%rowtype; 
     begin 
       for c1cur in c1 loop 
         for c2cur in c2(c1cur.deptno,'MANAGER')loop 
           dbms_output.put_line(c1cur.deptno||':'||c2cur.ename||'---'||c2cur.sal); 
         end loop; 
       end loop; 
     end; 
     / 
10:CLARK---2450 
20:JONES---2975 
30:BLAKE---2850

PL/SQL procedure successfully completed. 
Elapsed: 00:00:00.02

(4)引用游标/动态游标 
SQL>declare 
       type c1 is ref cursor;     --定义一个类型(ref cursor)弱类型  
       type c2 is ref cursor return emp%rowtype;   --定义一个强类型(返回的结果集有要求) 
       c0cur c1;              ---定义一个弱类型的游标变量 
       c1cur emp%rowtype; 
       c2cur dept%rowtype; 
    begin 
       dbms_output.put_line('all employees :'); 
       open c0cur for select * from emp; 
       loop 
          fetch c0cur into c1cur; 
          exit when c0cur%notfound; 
          dbms_output.put_line(c1cur.ename); 
       end loop; 
       dbms_output.put_line('all departments:'); 
       open c0cur for select * from dept; 
       loop 
         fetch c0cur into c2cur; 
         exit when c0cur%notfound; 
         dbms_output.put_line(c2cur.dname); 
       end loop; 
       close c0cur; 
    end; 
   / 
all employees: 
SMITH 
ALLEN 
WARD 
JONES 
MARTIN 
BLAKE 
CLARK 
SCOTT 
KING 
TURNER 
ADAMS 
JAMES 
FORD 
MILLER 
all departments: 
ACCOUNTING 
RESEARCH 
SALES 
OPERATIONS

PL/SQL procedure successfully completed. 
Elapsed: 00:00:00.02

(5)while循环 
SQL> set timing on 
SQL> set serverout on 
SQL> set pagesize 1000 
SQL> set linesize 400 
SQL> declare 
       cursor c1 is select loc from dept; 
       c1cur c1%rowtype; 
     begin 
       open c1; 
       fetch c1 into c1cur; 
       while c1%found loop 
       dbms_output.put_line('location:  '||c1cur.loc); 
       fetch c1 into c1cur;   ---与for循环不同,while循环需要将下一行的值赋给游标变量,否则会进入死循环,并报错 
       end loop; 
       close c1; 
     end; 
    / 
location:  NEW YORK 
location:  DALLAS 
location:  CHICAGO 
location:  BOSTON

PL/SQL procedure successfully completed. 
Elapsed: 00:00:00.10

死循环,报错: 
SQL> declare 
       cursor c1 is select loc from dept; 
       c1cur c1%rowtype; 
     begin 
       open c1; 
       fetch c1 into c1cur; 
       while c1%found loop 
       dbms_output.put_line('location:  '||c1cur.loc); 
       end loop; 
       close c1;  
     end; 
     / 
location:  NEW YORK 
location:  NEW YORK 
location:  NEW YORK 
location:  NEW YORK 
location:  NEW YORK 
declare 

ERROR at line 1: 
ORA-04030: out of process memory when trying to allocate 16328 bytes (koh-kghu sessi,pl/sql vc2)

执行时,单个进程就导致cpu 100%,因此游标还是要小心使用的!

(6)利用游标来更新(update) 
6.1 声明更新显示游标: 
   Cursor 游标名IS  SELECT 语句   For Update [ Of 更新列列名]; 
6.2 使用显示游标当前记录来更新: 
   Update  表名   SET   更新语句  Where   Current  Of   游标名;

1.所有人普调 
SQL> declare 
       cursor c1 is select * from emp for update of sal; 
       c1cur c1%rowtype; 
       saladd emp.sal%type; 
       salnew emp.sal%type; 
     begin 
       for c1cur in c1 loop 
         saladd:=c1cur.sal*0.2;  --所有员工加薪20% 
           if saladd<300 then 
             salnew:=c1cur.sal+300;   --加薪不足300的,按300加 
             dbms_output.put_line(c1cur.ename||':'||'new salary '||salnew); 
           else 
             salnew:=c1cur.sal+saladd; 
             dbms_output.put_line(c1cur.ename||':'||'new salary '||salnew); 
           end if; 
             update emp set sal=salnew where current of c1; 
       end loop; 
     end ; 
     / 
SMITH:new salary 1300  ---原来工资1000 
ALLEN:new salary 2304 
WARD:new salary 1800 
JONES:new salary 4284 
MARTIN:new salary 1800 
BLAKE:new salary 4104 
CLARK:new salary 3528 
SCOTT:new salary 4320 
KING:new salary 7200 
TURNER:new salary 2160 
ADAMS:new salary 1620 
JAMES:new salary 1450 
FORD:new salary 4320 
MILLER:new salary 1872

PL/SQL procedure successfully completed. 
Elapsed: 00:00:00.04

2.按照部门来调整 
declare                
   cursor c1 is select * from emp for update of sal; 
   c1cur c1%rowtype;   
   salnew emp.sal%type; 
begin                  
   for c1cur in c1 loop 
   case                ---必须包含所有的分类,否则会报错ORA-06592: CASE not found while executing CASE statement 
      when c1cur.deptno=10 
      then salnew:=c1cur.sal*1.1; 
      dbms_output.put_line(c1cur.ename||':'||'new salary '||salnew); 
      when c1cur.deptno=20 
      then salnew:=c1cur.sal*1.15; 
      dbms_output.put_line(c1cur.ename||':'||'new salary '||salnew); 
      when c1cur.deptno=30 
      then salnew:=c1cur.sal*1.2; 
      dbms_output.put_line(c1cur.ename||':'||'new salary '||salnew); 
      when c1cur.deptno=40 
      then salnew:=c1cur.sal*1.3; 
      dbms_output.put_line(c1cur.ename||':'||'new salary '||salnew); 
   end case; 
      update emp set sal=salnew where current of c1; 
   end loop; 
end; 
/

SMITH:new salary 1495 
ALLEN:new salary 2764.8 
WARD:new salary 2160 
JONES:new salary 4926.6 
MARTIN:new salary 2160 
BLAKE:new salary 4924.8 
CLARK:new salary 3880.8 
SCOTT:new salary 4968 
KING:new salary 7920 
TURNER:new salary 2592 
ADAMS:new salary 1863 
JAMES:new salary 1740 
FORD:new salary 4968 
MILLER:new salary 2059.2 
LITING:new salary 7800

PL/SQL procedure successfully completed. 
Elapsed: 00:00:00.07

3.符合if条件的 
declare                
   cursor c1 is select * from emp for update of sal; 
   c1cur c1%rowtype;   
   salnew emp.sal%type; 
begin                  
   for c1cur in c1 loop 
     if c1cur.deptno=20 then 
        salnew:=c1cur.sal*5-8000; 
        dbms_output.put_line(c1cur.ename||':'||'new salary '||salnew); 
     else   
        salnew:=c1cur.sal;        
     end if; 
        update emp set sal=salnew where current of c1; 
   end loop; 
end; 

SMITH:new salary 1525 
JONES:new salary 6633 
SCOTT:new salary 6840 
ADAMS:new salary 1315 
FORD:new salary 6840

PL/SQL procedure successfully completed. 
Elapsed: 00:00:00.05

4.以平均值为分界 
SQL> select avg(sal) from emp;  平均工资3715 
  AVG(SAL) 
---------- 
      3715 
      
SQL> declare 
  2  cursor c1 is select empno,ename,sal,deptno,avg(sal) over(partition by deptno) as depavg from emp for update of sal;
  3  c1cur c1%rowtype; 
  4  salnew emp.sal%type; 
  5  begin 
  6  for c1cur in c1 loop 
  7  if c1cur.sal>c1cur.depavg then 
  8  salnew:=c1cur.sal+50;    ---高于平均工资的奖金发50 
  9  dbms_output.put_line(c1cur.ename||':'||'new salary '||salnew);  
10  else 
11  salnew:=c1cur.sal+100;   ---低于平均工资的奖金发100 
12  dbms_output.put_line(c1cur.ename||':'||'new salary '||salnew); 
13  end if; 
14  update emp set sal=salnew where current of c1; 
15  end loop; 
16  end; 
17  / 
CLARK:new salary 3980 
MILLER:new salary 2160 
KING:new salary 7970 
JONES:new salary 4976 
SMITH:new salary 1595 
SCOTT:new salary 5018 
FORD:new salary 5071 
ADAMS:new salary 1415 
WARD:new salary 2260 
TURNER:new salary 2692 
ALLEN:new salary 2814 
JAMES:new salary 1840 
MARTIN:new salary 2260 
BLAKE:new salary 4974 
LITING:new salary 7900

PL/SQL procedure successfully completed. 
Elapsed: 00:00:00.47

(7)利用游标来删除(delete) 
7.1 声明删除显示游标: 
   Cursor 游标名IS  SELECT 语句   For Delete; 
7.2 使用显示游标当前记录来更新或删除: 
   Delete  From  表名   Where   Current  Of   游标名;

SQL> create table emp1 as select * from emp; 
Table created. 
Elapsed: 00:00:03.05

SQL> declare 
       cursor c1 is select ename,job from emp1 for update; 
       e_job emp1.job%type; 
       e_name emp1.ename%type; 
     begin 
       open c1; 
       loop 
       fetch c1 into e_name,e_job;  --顺序要跟上面的select顺序对应 
       exit when c1%notfound; 
          if e_job='ANALYST' then 
             delete from emp1 where current of c1; 
             dbms_output.put_line(e_name||':'||'deleted'); 
          end if; 
       end loop; 
       close c1; 
     end; 
     /  
SCOTT:deleted 
FORD:deleted

PL/SQL procedure successfully completed. 
Elapsed: 00:00:00.09

(8)利用游标来插入 
SQL> declare 
  2  cursor c1 is select * from emp1; 
  3  c1cur c1%rowtype; 
  4  begin 
  5  open c1; 
  6  loop 
  7  fetch c1 into c1cur; 
  8  exit when c1%notfound; 
  9  insert into emp values c1cur; 
10  dbms_output.put_line(c1cur.ename||': inserted'); 
11  end loop; 
12  close c1; 
13  end; 
14  / 
TINA: inserted 
BOBO: inserted 
LIO: inserted

PL/SQL procedure successfully completed. 
Elapsed: 00:00:00.11

SQL> select * from emp;  ---查看数据,插入成功

EMPNO ENAME      JOB         MGR HIREDATE     SAL       COMM     DEPTNO 
---------- ---------- ---------   ---------- --------- ---------- ---------- ---------- 
      7369 SMITH      CLERK       7902 17-DEC-80    1595    20 
      7499 ALLEN      SALESMAN   7698 20-FEB-81    2814        300    30 
      7521 WARD       SALESMAN   7698 22-FEB-81    2260        500    30 
      7566 JONES      MANAGER     7839 02-APR-81    4976    20 
      7654 MARTIN     SALESMAN   7698 28-SEP-81    2260       1400    30 
      7698 BLAKE      MANAGER     7839 01-MAY-81    4974    30 
      7782 CLARK      MANAGER     7839 09-JUN-81    3980    10 
      7788 SCOTT      ANALYST     7566 19-APR-87    5018    20 
      7839 KING       PRESIDENT      17-NOV-81    7970    10 
      7844 TURNER     SALESMAN   7698 08-SEP-81    2692       0      30 
      7876 ADAMS      CLERK       7788 23-MAY-87    1415    20 
      7900 JAMES      CLERK       7698 03-DEC-81    1840    30 
      7902 FORD       ANALYST     7566 03-DEC-81    5071    20 
      7934 MILLER     CLERK       7782 23-JAN-82    2160    10 
      7200 LITING     CLERK       7788 03-DEC-81    7900        500    40 
      6000 TINA       CLERK       7788 02-APR-86    4503        300    10 
      6221 BOBO       CLERK       7788 02-APR-86    4000        200    10 
      6307 LIO       CLERK       7788 02-APR-86    4409       0      10

转载于:https://www.cnblogs.com/xm1-ybtk/p/5112189.html

oracle中 游标实例相关推荐

  1. Oracle中游标Cursor介绍

    转自:http://zohan.group.iteye.com/group/wiki/2278-cursor Oracle中游标Cursor介绍 一  概念 游标是SQL的一个内存工作区,由系统或用户 ...

  2. Oracle中游标Cursor基本用法详解

    这篇文章主要介绍了Oracle中游标Cursor基本用法详解,还是比较全面的,具有一定参考价值,需要的朋友可以了解下. 查询 SELECT语句用于从数据库中查询数据,当在PL/SQL中使用SELECT ...

  3. oracle中游标分类,Oracle 游标分类以及实例

    /*Oracle游标,从字面理解就是游动的光标.用数据库语言来描述就是:游标是映射在结果集中一行数据上的位置实体, 有了游标,用户就可以访问结果集中的任意一行数据了,将游标放置到某行后,即可对该行数据 ...

  4. oracle中master实例,oracle基础(基本介绍)

    数据库 磁盘上存储的数据的集合 在物理上表现为数据文件.日志文件和控制文件等 在逻辑上以表空间形式存在 必须首先创建数据库,然后才能使用Oracle 数据库实例 每个启动的数据库都对应一个数据库实例, ...

  5. oracle中master实例,Oracle10g/11g RAC数据库中的Master实例、Owner实例和Past Image的概念PART3...

    实验第33步: 下面来验证: 节选实例1上的/u01/app/oracle/admin/RDBA/udump/rdba1_ora_18378.trc: /u01/app/oracle/admin/RD ...

  6. Oracle中游标(Cursor)介绍和使用

    一  概念  游标是SQL的一个内存工作区,由系统或用户以变量的形式定义.游标的作用就是用于临时存储从数据库中提取的数据块.在某些情况下,需要把数据从存放在磁盘的表中调到计算机内存中进行处理,最后将处 ...

  7. oracle中master实例,Oracle10g/11g RAC数据库中的Master实例、Owner实例和Past Image的概念PART2...

    实验第21步: 在任一个实例上执行: selectcount(*)from myviewwhere "OWNER_Instance" <> "MASTER_I ...

  8. oracle中rownum和row_number()

    row_number()over(partition by col1 order by col2)表示根据col1分组,在分组内部根据col2排序,而此函数计算的值就表示每组内部排序后的顺序编号(组内 ...

  9. oracle中角色和用户权限,Oracle用户、角色、权限管理

    用户在会话的权利上,应该有其他操作的权利:Oracle的用户和口令不区分大小写,真是让人大跌眼镜:Oralce中,所有用户必须明确被 create or replace type address as ...

最新文章

  1. 上海中考-哪些区是“地狱模式”?——2019上海中考数据观
  2. Linux 命令学习笔记
  3. webpack优化相关操作
  4. ansible调用callbacks插件实现结果nosql输出回调
  5. C++ pancake sort煎饼排序的实现算法(附完整源码)
  6. linux 双通道 磁盘,HP MSA2012SA 双通道 磁盘阵列配置说明 for linuxoracle
  7. Redis现网那些坑:用个缓存,还要为磁盘故障买单?
  8. 人渣scum服务器物品,人渣SCUM可以采集物品一览_可采集食物大全_可可网
  9. 设计模式二:结构型模式
  10. 阿里巴巴如何基于 Kubernetes 实践 CI/CD
  11. 一次订单号重复引起的事故,把我坑惨了!
  12. MinIO异常the region is wrong; expecting ‘us-east-1‘
  13. 哈哈...汗汗...
  14. 计算机组成原理(九)
  15. 阿里云智能身份证OCR文字识别
  16. clip-path的学习和简单使用
  17. noip2007 守望者的逃离 (贪心)
  18. python作业.创建两个文本框,一个按钮。第 1 个文本框绑定任意键事件,敲击键盘任意可显示字符,在交互窗口中显示该字符;第 2 个文本框绑定<a>键事件,敲击键盘 a 字符,在交互窗口中显示 10
  19. 《牛客刷verilog》Part III Verilog企业真题
  20. CTFSHOW-信息搜集

热门文章

  1. java输出流缓冲区内容清除,Java输入输出流与缓冲区的使用
  2. maven 如何看jar是否被修改_如何在线修改jar文件
  3. 【深度学习】基于Pytorch的卷积神经网络概念解析和API妙用(二)
  4. python【数据结构与算法】各进制转换-使用内置函数
  5. ecilpse连接oracle ojdbc驱动
  6. java default修饰符_Java修饰符看这一篇就够了
  7. 冒险岛公益服发布网_溧阳单面布来款定制,儿童冲锋衣厂家-大圣服装批发定制网...
  8. 商丘网络推广分析网站留不住用户的原因及SEO解决方法
  9. 企业网络推广之下的“盒马鲜生”新零售逐渐“破圈”而出
  10. 网络营销专员浅析网络营销优化对企业来说意味着什么?