1. 程式人生 > >oracle遊標的使用(二)

oracle遊標的使用(二)

copy str 創建 data- sel 字段 開封 tex 歷史

技術分享

逐行處理查詢結果,以編程的方式訪問數據

遊標的類型:

1、隱式遊標:在 PL/SQL 程序中執行DML SQL 語句時自動創建隱式遊標,名字固定叫sql。

2、顯式遊標:顯式遊標用於處理返回多行的查詢。
3、REF 遊標:REF 遊標用於處理運行時才能確定的動態 SQL 查詢的結果
隱式遊標:
在PL/SQL中使用DML語句時自動創建隱式遊標,隱式遊標自動聲明、打開和關閉,其名為 SQL,通過檢查隱式遊標的屬性可以獲得最近執行的 DML 語句的信息,隱式遊標的屬性有: %FOUND – SQL 語句影響了一行或多行時為 TRUE,%NOTFOUND – SQL 語句沒有影響任何行時為TRUE,%ROWCOUNT – SQL 語句影響的行數,%ISOPEN - 遊標是否打開,始終為FALSE

[sql] view plain copy
  1. BEGIN
  2. UPDATE t_bjqk SET fBL = fBL - 2 WHERE fBJDM=‘1461‘;
  3. IF SQL%FOUND THEN
  4. dbms_output.put_line(‘這次更新了‘ || SQL%ROWCOUNT);
  5. ELSE
  6. dbms_output.put_line(‘一行也沒有更新‘ );
  7. END IF;
  8. END;
  9. --SELECT * FROM t_bjqk;
[sql] view plain copy
  1. select中有兩個中比較常見的異常: 1. NO_DATA_FOUND 2. TOO_MANY_ROWS
  2. SQL> declare
  3. 2 sname1 student.sname%TYPE;
  4. 3 begin
  5. 4 select sname into sname1 from student;
  6. 5 if sql%found then
  7. 6 dbms_output.put_line(sql%rowcount);
  8. 7 else
  9. 8 dbms_output.put_line(‘沒有找到數據‘);
  10. 9 end if;
  11. 10 exception
  12. 11 when too_many_rows then
  13. 12 dbms_output.put_line(‘查找的行記錄多於1行‘);
  14. 13 when no_data_found then
  15. 14 dbms_output.put_line(‘未找到匹配的行‘);
  16. 15 end;
  17. 16 /
  18. 查找的行記錄多於1行
  19. PL/SQL procedure successfully completed
  20. SQL>

顯式遊標:

技術分享 sqlserver與oracle的不同之處在於: 最後sqlserver會deallocate 丟棄遊標,而oracle只有前面四步: 聲明遊標、打開遊標、使用遊標讀取記錄、關閉遊標。
顯式遊標的使用: [sql] view plain copy
  1. declare
  2. sname varchar2( 20); --聲明變量
  3. cursor student_cursor is select sname from student ; --聲明遊標
  4. begin
  5. open student_cursor; --打開遊標
  6. fetch student_cursor into sname; --讓遊標指針往下移動
  7. while student_cursor%found --判斷遊標指針是否指向某行記錄
  8. loop --遍歷
  9. dbms_output.put_line (‘學生姓名‘ ||sname );
  10. fetch student_cursor into sname;
  11. end loop;
  12. close student_cursor;
  13. end;
  14. ------------------------------------有參數遊標-------------------------------
  15. declare
  16. sname student.sname%type;
  17. sno student.sno%type;
  18. cursor student_cursor (input_sno number) is
  19. select s.sname, s.sno from student s where s.sno > input_sno; --聲明帶參數的遊標
  20. begin
  21. sno := &請輸入學號; --要求從客戶端輸入參數值,"&"相當於占位符;
  22. open student_cursor( sno); --打開遊標,並且傳遞參數
  23. fetch student_cursor into sname, sno; --移動遊標
  24. while student_cursor% found
  25. loop
  26. dbms_output.put_line (‘學號為:‘ ||sno ||‘姓名為:‘ ||sname );
  27. fetch student_cursor into sname,sno;
  28. end loop;
  29. close student_cursor;
  30. end;
  31. ------------------------------------循環遊標-------------------------------
  32. -- Created on 18-1月-15 by 永文
  33. declare
  34. stu1 student%rowtype ; --這裏也不需要定義變量來接收fetch到的值
  35. cursor student_cursor is select * from student ;
  36. begin
  37. open student_cursor; --這裏不需要開啟遊標
  38. for stu1 in student_cursor
  39. loop
  40. dbms_output.put_line (‘學生學號:‘ ||stu1.sno ||‘學生姓名:‘ ||stu1.sname );
  41. fetch student_cursor into stu1; --也不需要fetch了
  42. end loop;
  43. close student_cursor; --這裏也不需要關閉遊標
  44. end;
  45. ------------------------------------使用遊標更新行-------------------------------
  46. declare
  47. stu1 student%rowtype ;
  48. cursor student_cursor is select * from student s where s.sno in (2 ,3 ) for update;--創建更新遊標
  49. begin
  50. open student_cursor;
  51. fetch student_cursor into stu1;--移動遊標
  52. while student_cursor%found --遍歷遊標,判斷是否指向某個值
  53. loop
  54. update student set sage = sage + 10 where current of student_cursor;--通過遊標中的信息更新數據
  55. fetch student_cursor into stu1;--移動遊標
  56. end loop;
  57. close student_cursor;
  58. end;
  59. declare
  60. stu1 student%rowtype ;
  61. cursor student_cursor is select * from student s where s.sno in (2 ,3 ) for update;--創建更新遊標
  62. begin
  63. open student_cursor;
  64. -- fetch student_cursor into stu1;--移動遊標
  65. -- while student_cursor%found--遍歷遊標,判斷是否指向某個值
  66. loop
  67. fetch student_cursor into stu1 ;--移動遊標
  68. exit when student_cursor %notfound ;
  69. update student set sage = sage + 10 where current of student_cursor;--通過遊標中的信息更新數據
  70. end loop;
  71. close student_cursor;
  72. end;
  73. ------------------------------------使用fetch ... bulk collect into-------------------------------
  74. declare
  75. cursor my_cursor is select ename from emp where deptno= 10; --聲明遊標
  76. type ename_table_type is table of varchar2 (10 );--定義一種表類型,表中的屬性列為varchar2類型
  77. ename_table ename_table_type;--通過上面定義的類型來定義變量
  78. begin
  79. open my_cursor; --打開遊標
  80. fetch my_cursor bulk collect into ename_table; --移動遊標
  81. for i in 1 ..ename_table.count loop
  82. dbms_output.put_line(ename_table(i));
  83. end loop ;
  84. close my_cursor;
  85. end;
  86. -----------------------------------顯示遊標題目--------------------------------------
  87. SQL > select * from student ;
  88. XH XM
  89. ---------- ----------
  90. 1 A
  91. 2 B
  92. 3 C
  93. 4 D
  94. SQL > select * from address ;
  95. XH ZZ
  96. ---------- ----------
  97. 2 鄭州
  98. 1 開封
  99. 3 洛陽
  100. 4 新鄉
  101. 完成的任務 :給表student添加一列zz ,是varchar2 (10 )類型;
  102. 再從address中,將zz字段的數值取出來,對應的插入到
  103. student新增的zz列中。
  104. 即:得到的結果:student表中,是:
  105. XH XM ZZ
  106. -- ---------- ------
  107. 1 A 開封
  108. 2 B 鄭州
  109. 3 C 洛陽
  110. 4 D 新鄉
  111. declare
  112. stu1 student %rowtype ;
  113. add1 address %rowtype ;
  114. cursor student_cursor is select * from student for update; --聲明更新遊標
  115. cursor address_cursor is select * from address ; --聲明遊標
  116. begin
  117. open student_cursor ; --打開遊標
  118. fetch student_cursor into stu1; --移動遊標
  119. while student_cursor% found--判斷遊標是否指向某條記錄
  120. loop
  121. open address_cursor ; --打開另外一個遊標
  122. fetch address_cursor into add1 ; --移動遊標
  123. while address_cursor %found--判斷遊標是否指向某條記錄
  124. loop
  125. if add1.xh = stu1.xh then--判斷兩個遊標所指向的記錄中xh的值是否相等
  126. update student s set s.zz = add1.zz where current of student_cursor; --假如相等就更新遊標所指向的記錄值
  127. end if;
  128. fetch address_cursor into add1 ; --移動遊標
  129. end loop;
  130. close address_cursor ; --關閉遊標
  131. fetch student_cursor into stu1 ; --移動遊標
  132. end loop;
  133. close student_cursor ; --關閉遊標
  134. end;
REF遊標也叫動態遊標:
qREF 遊標和遊標變量用於處理運行時動態執行的 SQL 查詢 q創建遊標變量需要兩個步驟: q聲明 REF 遊標類型 q聲明 REF 遊標類型的變量 q用於聲明 REF 遊標類型的語法為:
TYPE <ref_cursor_name> IS REF CURSOR
[RETURN <return_type>];
[sql] view plain copy
  1. -----------------------------------ref遊標---------------------------------
  2. declare
  3. type ref_cursor is ref cursor; --聲明一個ref遊標類型
  4. tab_cursor ref_cursor ;--聲明一個ref遊標
  5. sname student.xm %type ;
  6. sno student.xh %type ;
  7. tab_name varchar2 (20 );
  8. begin
  9. tab_name := ‘&tab_name‘; --接收客戶輸入的表明
  10. if tab_name = ‘student‘ then
  11. open tab_cursor for select xh ,xm from student ; --打開ref遊標
  12. fetch tab_cursor into sno ,sname ;--移動遊標
  13. while tab_cursor %found
  14. loop
  15. dbms_output.put_line (‘學號:‘ ||sno ||‘姓名:‘ ||sname );
  16. fetch tab_cursor into sno ,sname ;
  17. end loop;
  18. close tab_cursor ;
  19. else
  20. dbms_output.put_line (‘沒有找到你想要找的表數據信息‘ );
  21. end if;
  22. end;
  23. -----------------------------------ref遊標題目---------------------------------
  24. SQL > select * from student ;
  25. XH KC
  26. ---------- ----------
  27. 1 語文
  28. 1 數學
  29. 1 英語
  30. 1 歷史
  31. 2 語文
  32. 2 數學
  33. 2 英語
  34. 3 語文
  35. 3 英語
  36. 9 rows selected
  37. SQL >
  38. 完成的任務 :
  39. 生成student2表 (xh number, kc varchar2 (50 ));
  40. 對應於每一個學生,求出他的總的選課記錄,把每個學生的選課記錄插入到student2表中。
  41. 即,student2中的結果如下:
  42. XH KC
  43. --- -------------------------------------------
  44. 1 語文數學英語歷史
  45. 2 語文數學英語
  46. 3 語文英語
  47. create table student2 (xh number, kc varchar2 (50 ));
  48. declare
  49. kcs varchar2 (50 );
  50. kc varchar2 (50 );
  51. type ref_cursor is ref cursor; --聲明一個ref遊標類型
  52. stu_cursor ref_cursor ;--定義一個ref遊標類型的變量
  53. type tab_type is table of number; --聲明一個table類型
  54. tab_xh tab_type ;--定義一個表類型的變量
  55. cursor cursor_xh is select distinct( xh) from student; --聲明一個遊標
  56. begin
  57. open cursor_xh; --打開遊標
  58. fetch cursor_xh bulk collect into tab_xh; --提取數據到表中
  59. for i in 1 .. tab_xh.count
  60. loop
  61. kcs :=‘‘ ;
  62. open stu_cursor for select kc from student s where s.xh = tab_xh(i ); --打開ref遊標
  63. fetch stu_cursor into kc ; --移動遊標
  64. while stu_cursor %found
  65. loop
  66. kcs := kc ||kcs ; --連接字符串使用||而不是+
  67. fetch stu_cursor into kc ; --移動遊標
  68. end loop;
  69. insert into student2 (xh , kc ) values( i, kcs);
  70. close stu_cursor ;
  71. end loop;
  72. close cursor_xh ;
  73. end;

oracle遊標的使用(二)