`
yde986
  • 浏览: 97759 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

Oracle 游标的使用(二)

 
阅读更多
Sql代码 复制代码 收藏代码
  1. --ref 游标   
  2. /*   
  3.     显示游标 多行   
  4.     隐含游标 数据操纵语言 DML 和单行select into语句   
  5.        
  6.     1.定义游标    
  7.         指定游标所对应的select结果集语句   
  8.         CURSOR cursor_name IS select_statement;   
  9.            select_statement:查询语句   
  10.     2.打开游标   
  11.         OPEN cursor_name;   
  12.          执行游标所对应的select_statement,将结果暂时存放在游标结果集中   
  13.     3.提取数据   
  14.          使用fetch语句提取游标数据,fetch每次只能提取一行;fetch..bulk collect into可以提取多行   
  15.          FETCH cursor_name into variable...;   
  16.              variable 接受游标数据的变量   
  17.          FETCH cursor_name BULK COLLECT INTO collection...;   
  18.              collection 接收游标数据的集合变量   
  19.     4.关闭游标   
  20.          提取完数据,关闭游标,释放结果集   
  21.          CLOSE cursor_name;   
  22.             
  23.             
  24.             
  25.     *游标属性   
  26.       cursor_name%ISOPEN  游标是否已打开   
  27.       cursor_name%FOUND   FETCH语句执行后,用来判断是否有数据被提取   
  28.       cursor_name%NOTFOUND 同上   
  29.       cursor_name%ROWCOUNT 目前已经fetch的行数   
  30.         
  31. */   
  32. --隐含游标   
  33. DECLARE    
  34.   v_name varchar2(30);   
  35. BEGIN  
  36.   select ename into v_name from emp where empno = 7788;   
  37.   CASE  
  38.   WHEN SQL%FOUND THEN  
  39.     dbms_output.put_line('隐身游标的行数肯定是:'||SQL%ROWCOUNT||',查询的结果:'||v_name);   
  40.     --隐身游标的行数肯定是:1,查询的结果:SCOTT   
  41.   END CASE;   
  42. END;   
  43.   
  44. --显示游标   
  45.   
  46. --fetch提取一行数据   
  47. DECLARE  
  48.    CURSOR emp_cs is select ename,job from emp;--声明游标   
  49.    v_name emp.ename%type;   
  50.    v_job  emp.job%type;   
  51. BEGIN  
  52.    OPEN emp_cs;   
  53.    LOOP--因为fetch只提取一条数据,所以用循环多次提取   
  54.         FETCH emp_cs INTO v_name,v_job;   
  55.         EXIT WHEN emp_cs%NOTFOUND;--当游标中没有数据时,退出循环   
  56.         dbms_output.put_line(emp_cs%ROWCOUNT||'--'||v_name||'--'||v_job);   
  57.    END LOOP;   
  58.    CLOSE emp_cs;   
  59. END;   
  60.   
  61. --FETCH ...BULK COLLECTION 提取多行数据   
  62. DECLARE  
  63.    --声明存储多行数据的集合类型   
  64.    TYPE v_table_type IS TABLE OF VARCHAR2(30);   
  65.    name_table v_table_type;   
  66.    job_table v_table_type;   
  67.    CURSOR emp_cs IS select ename,job from emp;   
  68. BEGIN  
  69.    OPEN emp_cs;   
  70.    FETCH emp_cs BULK COLLECT INTO name_table,job_table; --两个嵌套表类型不需要初始化   
  71.    FOR i IN 1..name_table.count LOOP   
  72.        dbms_output.put_line(name_table(i)||'--'||job_table(i));   
  73.    END LOOP;   
  74.    CLOSE emp_cs;   
  75. END;   
  76.   
  77. --分页提取,每次提取固定条数   
  78. DECLARE  
  79.    type v_table_type IS TABLE OF int;   
  80.    no_tab v_table_type;   
  81.    pageNo int :=5;--5条一页   
  82.    nums int:=0;--已经输出的条数   
  83.    CURSOR emp_cs IS select empno from emp;   
  84. BEGIN  
  85.    --OPEN emp_cs;   
  86.    IF NOT emp_cs%ISOPEN THEN  
  87.       OPEN emp_cs;   
  88.    END IF;   
  89.    LOOP--LIMIT语句限制每次提请的条数,从上次游标rowcount处开始   
  90.       FETCH emp_cs BULK COLLECT INTO no_tab LIMIT pageNo;   
  91.       --打印刚获取的数据(5条),右边界计算方法:游标总共fetch的条数-已经输出的条数   
  92.       FOR I IN 1..(emp_cs%ROWCOUNT - nums) LOOP   
  93.           dbms_output.put_line(no_tab(i));   
  94.       END LOOP;   
  95.       dbms_output.new_line;   
  96.       nums := emp_cs%ROWCOUNT;--从新设置已输出的条数   
  97.       /*   
  98.        --这一句放到最后,因为知道emp表中共有14条记录,可以分为3页,第3次Fecth只有4条数据,   
  99.        --这时候已经是NOTFOUND了,如果放到输出前面的话,后4条就不能被输出了   
  100.       */   
  101.       EXIT WHEN emp_cs%NOTFOUND;    
  102.    END LOOP;   
  103.    CLOSE emp_cs;   
  104. END;   
  105.   
  106.   
  107. --游标 记录变量   
  108. DECLARE  
  109.    CURSOR emp_cs IS select ename,job from emp;   
  110.    v_record emp_cs%ROWTYPE;--游标行类型定义record   
  111. BEGIN  
  112.    OPEN emp_cs;   
  113.    LOOP   
  114.       FETCH emp_cs INTO v_record;   
  115.       EXIT WHEN emp_cs%NOTFOUND;   
  116.       dbms_output.put_line(v_record.ename||'--'||v_record.job);   
  117.    END LOOP;   
  118.    CLOSE emp_cs;   
  119. END;   
  120.   
  121.   
  122. --参数游标 就是差不多相当与函数了 根据不同的参数值有不同的游标数据   
  123. --参数一般会在游标的select语句中使用,否则也就没意义了   
  124. /*   
  125.    CURSOR cursor_name(parametr_name datatype...) IS select_statement;   
  126.    *参数只能定义类型,不能定义长度,   
  127. */   
  128.   
  129. DECLARE    
  130.    CURSOR emp_cs(param1 varchar2) IS select ename from emp where job =param1;   
  131.    v_name emp.ename%type;   
  132.    v_job varchar2(30) := '&job';   
  133. BEGIN  
  134.    OPEN emp_cs(v_job);   
  135.    LOOP   
  136.        FETCH emp_cs INTO v_name;   
  137.        EXIT WHEN emp_cs%NOTFOUND;   
  138.        dbms_output.put_line(v_name);   
  139.    END LOOP;   
  140.    CLOSE emp_cs;   
  141. END;   
  142.   
  143.   
  144.   
  145. --使用游标更新或删除数据   
  146. /*   
  147.    游标不仅可以查询数据,也可以修改数据,由于游标是操作的多条数据更新,为   
  148.    保证事物的原子性,我也不知道怎么称呼,反正就是防止游标中的数据行在修改的过程中   
  149.    有其它的事务修改这些列 要使用FOR UPDATE 子句   
  150.    如:游标中有5条数据,你这时正执行修改第3条数据,而这时另一个事务修改了第4条数据。   
  151.    而游标是临时缓存结果集,4的修改就不会被看到。这样就乱套了   
  152.       
  153.    CURSOR cursor_name(param datatype) IS    
  154.     select_statement FOR UPDATE [OF column_reference][NOWAIT];   
  155.        
  156.     FOR UPDATE在游标结果集数据行上加行共享锁,防止其它用户在相应   
  157.     行上执行DML操作。   
  158. */   
  159. DECLARE  
  160.     CURSOR emp_cs IS select comm from emp FOR UPDATE;   
  161.     v_comm number(7,2);   
  162. BEGIN  
  163.     OPEN emp_cs;   
  164.     LOOP   
  165.        FETCH emp_cs INTO v_comm;   
  166.        EXIT WHEN emp_cs%NOTFOUND;   
  167.        IF v_comm is null THEN  
  168.           UPDATE emp SET comm=1 WHERE CURRENT OF emp_cs;   
  169.        END IF;   
  170.     END LOOP;   
  171.     CLOSE emp_cs;   
  172. END;   
  173. commit;   
  174.   
  175. /*   
  176. 游标for循环   
  177. 简化了对游标的处理,使用游标for循环时,oracle会隐含的打开游标、   
  178. 提取数据并关闭游标   
  179. */   
  180. --1   
  181. DECLARE  
  182.     CURSOR emp_cs IS select ename,job from emp;   
  183. BEGIN  
  184.     FOR emp_record IN emp_cs LOOP--emp_record是隐含定义的记录变量名   
  185.         dbms_output.put_line(emp_cs%ROWCOUNT||'-'||emp_record.ename);   
  186.     END LOOP;   
  187. END;   
  188.   
  189. --2 在游标for循环中直接是哦那个select语句定义游标   
  190. --不过这样就不能使用游标属性了,因为没有游标名字   
  191. BEGIN  
  192.     FOR emp_record IN (select ename,job from emp) LOOP   
  193.         dbms_output.put_line(emp_record.ename);   
  194.     END LOOP;   
  195. END;   
  196.   
  197.   
  198. /*   
  199.     使用游标变量   
  200.     使用显示游标时,需要在定义部分指定所对应的静态select语句;   
  201.     当使用游标变量时,就可在打开游标变量时指定其所对应的select语句。   
  202.     定义游标变量   
  203.     TYPE ref_type IS REF CURSOR[RETURN return_type];   
  204.     cursor_var ref_type;   
  205. */   
  206. --exp1   
  207. DECLARE  
  208.     TYPE emp_cursor_type IS REF CURSOR--定义一个游标变量类型   
  209.     emp_cs emp_cursor_type;--使用这个游标类型定义一个游标变量   
  210.     emp_record emp%ROWTYPE;   
  211. BEGIN  
  212.     OPEN emp_cs FOR select * from emp;--打开游标变量时指定其所对应的select语句   
  213.     LOOP    
  214.        FETCH emp_cs INTO emp_record;--取数据就和普通的游标一样了   
  215.        EXIT WHEN emp_cs%NOTFOUND;   
  216.        dbms_output.put_line(emp_record.ename);   
  217.     END LOOP;   
  218.     CLOSE emp_cs;   
  219. END;   
  220.   
  221. --exp2 定义游标变量是指定返回类型(智能是record)   
  222. DECLARE  
  223.     TYPE v_record_type IS RECORD(   
  224.          name varchar2(10),sal number   
  225.     );   
  226.     TYPE v_cursor_type IS REF CURSOR RETURN v_record_type;--返回上面定义的record类型   
  227.     --声明一个record变量,一个cursor变量   
  228.     v_record v_record_type;   
  229.     v_cursor v_cursor_type;   
  230. BEGIN  
  231.     OPEN v_cursor FOR select ename,sal from emp where deptno=10;   
  232.     LOOP    
  233.        FETCH v_cursor INTO v_record;   
  234.        EXIT WHEN v_cursor%NOTFOUND;   
  235.        dbms_output.put_line(v_record.name||'-'||v_record.sal);   
  236.     END LOOP;   
  237.     CLOSE v_cursor;   
  238. END;  
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics