码迷,mamicode.com
首页 > 其他好文 > 详细

7、游标

时间:2016-07-20 01:05:27      阅读:212      评论:0      收藏:0      [点我收藏+]

标签:

一、游标语法概念和案例

技术分享
  1 一.课前回顾
  2 存储过程的用途:
  3 (1)它相当于方法,所以可以通过java代码调用存储过程,
  4 使得存储过程的执行时机是可控的!(想什么时候执行都可以)
  5 (2)存储过程中还可以调用游标!
  6 (3)存储过程中可以执行赋值,sql的增删改查(查一条)
  7 1.存储过程(有参数)
  8 create or replace procedure p_名字
  9   (v_变量名 in/out 数据类型)
 10 is|as
 11   定义变量
 12 begin
 13    执行内容
 14 end;
 15 
 16 2.存储过程(无参数)
 17 create or replace procedure p_名字
 18 is|as
 19   定义变量
 20 begin
 21    执行内容
 22 end;
 23 
 24 3.单纯的调用存储过程
 25 exec p_名字(实参|无参);
 26 
 27 4.如果在plsql中调用存储过程,
 28 p_名字(实参|无参);
 29 
 30 5.异常
 31 notfound → select ...into 的时候没有查到
 32 others → 其他异常类型,必须放在异常列表的最后,
 33  相当于java异常中的exception
 34 
 35 二.游标
 36 用途:查询批量数据,放入一个游标(集合)
 37 2.1 使用步骤
 38 (1)定义游标(相当于定义了一个集合)
 39  cursor c_游标名 is 查询语句;
 40 
 41 (2)打开游标
 42 open c_游标名;
 43 
 44 (3)提取游标内容
 45 fetch c_游标名 into 变量1,变量2,...;
 46 
 47 用循环去提取
 48 while c_游标名%found  loop
 49    读取,打印,赋值
 50    fetch c_游标名 into 变量1,变量2,...;
 51 end loop;
 52 
 53 loop循环
 54 loop
 55    fetch c_游标名 into 变量1,变量2,...;
 56    读取,打印,赋值
 57    exit when c_游标名%notfound;
 58 end loop;
 59 
 60 (4)关闭游标
 61 close c_游标名;
 62 
 63 (5)使用for 循环隐式打开游标,提取游标,关闭游标
 64 (使用for循环不用显示的打开游标,提取游标,关闭游标)
 65 --隐式的打开游标
 66 for i in c_游标名
 67 loop
 68     --隐式的提取游标内容
 69     读取,赋值,打印i.查询出的表字段
 70 
 71 --隐式关闭游标
 72 end loop;
 73 
 74 (6)存储过程和游标结合的大概
 75 create or replace procedure p_过程名(v_list out varchar2)
 76 is|as
 77 begin
 78    v_list:=c_游标名;
 79 end;
 80 
 81 2.2 使用游标提取emp表中的所有数据
 82 方法1:使用while循环提取游标内容
 83 set serverout on
 84 declare
 85   --定义存储提取内容的变量
 86   v_ename emp.ename%type;
 87   v_sal emp.sal%type;
 88   
 89   --定义游标
 90   cursor c_emp is select ename,sal from emp;
 91 begin
 92   --打开游标
 93   open c_emp;
 94   
 95   --提取游标内容
 96   fetch c_emp into v_ename,v_sal ;
 97 
 98   --while循环打印游标读取的内容
 99   while c_emp%found loop
100      dbms_output.put_line(c_emp%rowcount||--||v_ename||--||v_sal);
101      fetch c_emp into v_ename,v_sal ;  
102   end loop;
103 
104   --关闭游标
105   close c_emp;
106 end;
107 /
108 
109 方法2:使用do-while循环提取游标内容
110 set serverout on
111 declare
112   --定义存储提取内容的变量
113   v_ename emp.ename%type;
114   v_sal emp.sal%type;
115   
116   --定义游标
117   cursor c_emp is select ename,sal from emp;
118 begin
119   --打开游标
120   open c_emp;
121   
122   --do-while循环打印游标读取的内容
123   loop
124      --提取游标内容
125      fetch c_emp into v_ename,v_sal ;  
126      dbms_output.put_line(c_emp%rowcount||--||v_ename||--||v_sal);
127      exit when c_emp%notfound;
128   end loop;
129 
130   --关闭游标
131   close c_emp;
132 end;
133 /
134     
135 方法2:使用for循环提取游标内容
136 
137 set serverout on
138 declare
139   cursor c_emp is select ename,sal from emp;
140 begin
141   for i in c_emp
142   loop
143      dbms_output.put_line(c_emp%rowcount||--||i.ename||--||i.sal);
144   end loop;
145 end;
146 /
147 
148 2.3 查询所有的员工编号和工资,如果工资小于1200则在原来的基础上加50
149 
150 --方法1:使用while循环
151 set serverout on
152 declare
153   --定义游标提取存放数据的变量
154   v_empno1 emp.empno%type;
155   v_sal1 emp.sal%type;
156   
157   --定义游标
158   cursor c_emp is select empno,sal from emp;
159 begin
160   --打开游标
161   open c_emp;
162   
163   --提取游标中的一行数据
164   fetch c_emp into v_empno1,v_sal1;
165   while c_emp%found 
166   loop
167      dbms_output.put_line(v_empno1||--||v_sal1);
168      if v_sal1<=1200 then
169         update emp set sal=v_sal1+50 where empno=v_empno1;
170         dbms_output.put_line(v_empno1||修改成功);
171         select empno,sal into v_empno1,v_sal1 from emp
172          where empno=v_empno1;
173          dbms_output.put_line(v_empno1||--||v_sal1);
174      end if;
175      fetch c_emp into v_empno1,v_sal1;
176   end loop;
177   close c_emp;
178 end;
179 /
180 
181 
182 
183 --方法2:使用do-while==loop循环
184 set serverout on
185 declare
186   --定义游标提取存放数据的变量
187   v_empno1 emp.empno%type;
188   v_sal1 emp.sal%type;
189   
190   --定义游标
191   cursor c_emp is select empno,sal from emp;
192 begin
193   --打开游标
194   open c_emp;
195   
196   fetch c_emp into v_empno1,v_sal1;
197   loop
198      
199      dbms_output.put_line(v_empno1||--||v_sal1);
200      if v_sal1<=1200 then
201         update emp set sal=v_sal1+50 where empno=v_empno1;
202         dbms_output.put_line(v_empno1||修改成功);
203         select empno,sal into v_empno1,v_sal1 from emp
204          where empno=v_empno1;
205          dbms_output.put_line(v_empno1||--||v_sal1);
206      end if;
207      fetch c_emp into v_empno1,v_sal1;
208      exit when c_emp%notfound;
209 
210   end loop;
211   close c_emp;
212 end;
213 /
214 
215 --方法3:使用 for in循环
216 set serverout on
217 declare
218   v_empno emp.empno%type;
219   v_sal emp.sal%type;
220   cursor c_emp is select empno,sal from emp;
221 begin
222   for i in c_emp
223   loop
224     dbms_output.put_line(c_emp%rowcount||--||i.empno||--||i.sal);
225     if i.sal<=1200 then
226        update emp set sal=i.sal+50 where empno=i.empno;
227        select empno,sal into v_empno,v_sal from emp where empno=i.empno ;
228 
229        dbms_output.put_line(i.empno||数据已经修改);
230        dbms_output.put_line(v_empno||--||v_sal);
231     end if;
232   end loop;
233 end; 
234 /
235   
236 2.4 定义有参数无返回值的游标
237 --题目:查询员工的编号和工资
238 set serverout on
239 declare
240   --定义有参数的游标
241   cursor c_emp(v_empno number)
242   is 
243     select empno,sal from emp where empno=v_empno;
244 begin
245   dbms_output.put_line(编号--工资);
246   for i in c_emp(7369)
247   loop
248     dbms_output.put_line(i.empno||--||i.sal);
249   end loop;
250 end;
251 /
252 
253 2.5 定义有参数有返回值类型的游标
254 --do-while循环
255 set serverout on
256 declare
257   --定义游标的返回值的列集
258   TYPE emp_record_type 
259   is RECORD(v_empno emp.empno%type,v_sal emp.sal%type );
260   
261   --定义游标的返回值类型
262   v_emp_record_type EMP_RECORD_TYPE;
263 
264   --定义有参数有返回值类型的游标
265   CURSOR c_emp(v_deptno emp.deptno%type)
266     RETURN EMP_RECORD_TYPE
267   IS
268     select empno,sal from emp where deptno=v_deptno;
269 
270 begin
271   --打开游标
272   open c_emp(20);
273   dbms_output.put_line(编号--工资);
274   loop
275     --提取游标内容
276     fetch c_emp into v_emp_record_type;
277      dbms_output.put_line(v_emp_record_type.v_empno||--||v_emp_record_type.v_sal);
278     exit when c_emp%notfound;
279   end loop;
280   close c_emp;
281 end;
282 /
283 
284 --for循环
285 set serverout on
286 declare
287   --定义游标的返回值的列集
288   TYPE emp_record_type 
289   is RECORD(v_empno emp.empno%type,v_sal emp.sal%type );
290 
291   --定义游标的返回值类型
292   v_emp_record_type EMP_RECORD_TYPE;
293 
294   --定义有参数有返回值类型的游标
295   CURSOR c_emp(v_deptno emp.deptno%type)
296     RETURN EMP_RECORD_TYPE
297   IS
298     select empno,sal from emp where deptno=v_deptno;
299 begin
300   dbms_output.put_line(编号--工资);
301   for i in c_emp(20)
302   loop
303     dbms_output.put_line(i.v_empno||--||i.v_sal);
304   end loop;
305 end;
306 /
游标语法概念和案例

二、显示游标、动态游标,动态sql

技术分享
  1  --1.显示游标的使用
  2  --在dos窗口中写plsql块要输出内容必须写下面这句话
  3  set serverout on
  4  declare
  5    --定义两个变量姓名和工资
  6    name emp.ename%type;
  7    sal emp.sal%type;
  8    
  9    --定义游标
 10    cursor cursor_emp is
 11      select ename,sal from emp;
 12  begin
 13  
 14  --开启右边
 15    open cursor_emp;
 16    loop
 17    --提取游标内容
 18       fetch cursor_emp into name,sal;
 19       exit when cursor_emp%notfound;
 20       dbms_output.put_line(||cursor_emp%rowcount||个雇员:||name||sal);
 21    end loop;
 22    
 23    --关闭游标
 24    close cursor_emp;
 25  end;
 26  
 27  --dos窗口中写必须用次符号来结束
 28  /
 29  
 30  --输出结果:
 31 第1个雇员:holly233.33
 32 第2个雇员:管未433.33
 33 
 34 --2.使用for in循环简化游标的读取自动结束
 35 set serverout on
 36 declare
 37    --定义游标
 38    cursor cursor_emp is
 39       select ename,sal from emp;
 40 begin
 41   --for in循环游标,当游标中没有数据时自动停止并关闭游标
 42    for i in cursor_emp
 43    loop
 44         dbms_output.put_line(||cursor_emp%rowcount||个雇员:||i.ename||i.sal);
 45    end loop; 
 46 end;
 47 /
 48 
 49 --3.动态有游标
 50 set serverout on
 51 declare
 52   --定义弱类型游标数据类型
 53   type cursor_type_scott is ref cursor;
 54   
 55   --定义一个游标变量
 56   cursor_scott cursor_type_scott;
 57   
 58   --定义两个循增量
 59   i emp%rowtype;
 60   j dept%rowtype;
 61   
 62 begin
 63   --游标读取员工表
 64   --打开游标并将内容放入游标变量
 65   open cursor_scott for select * from emp where deptno=20;
 66   loop
 67      --提取游标变量里的内容
 68     fetch cursor_scott into i;
 69     
 70     --循环提取结束条件
 71     exit when cursor_scott%notfound;
 72     dbms_output.put_line(i.ename||的雇佣日期是||i.hiredate);
 73   end loop;
 74   
 75   --游标读取部门表
 76   open cursor_scott for select * from dept where deptno in(10,20);
 77   loop
 78     fetch cursor_scott into j;
 79     exit when cursor_scott%notfound;
 80     dbms_output.put_line(j.deptno||表示||j.dname);
 81   end loop;
 82   
 83   --关闭游标
 84   close cursor_scott;
 85 end;
 86 /
 87 
 88 --输出结果为:
 89 管未的雇佣日期是03-3月 -14
 90 10表示ACCOUNTING
 91 20表示RESEARCH
 92 
 93 
 94 --4.动态sql创建表
 95 --根据用户输入的表名及字段名等参数动态创建表t1
 96 set serverout on
 97 declare
 98    table_name varchar2(20);--表名
 99    field1 varchar2(20);--字段名
100    datatype1 varchar2(20);-- 字段类型
101    field2 varchar2(20);--字段名
102    datatype2 varchar2(20);-- 字段类型
103    str_sql varchar2(500); --存放sql语句的变量
104    
105 begin
106    table_name:=t1;
107    field1:=id;
108    datatype1:=number;
109    field2:=name;
110    datatype2:=varchar2(20);
111    str_sql:=create table ||table_name||(||field1||  ||datatype1||,||field2|| ||datatype2||);
112    
113    --动态创建表
114    execute immediate str_sql;
115  
116 exception
117   when others then
118   dbms_output.put_line(操作失败!);
119 
120 end;
121 /
122 
123 运行结果:
124 PL/SQL 过程已成功完成。
125  desc t1;
126  名称                                      是否为空? 类型
127 ----------------------------------------- -------- ----------------------------
128 ID                                                 NUMBER
129 NAME                                               VARCHAR2(20)
130 
131 
132 --5.动态sql插入数据
133 set serverout on
134 declare
135    id number;--输入序号
136    name varchar2(20);  --输入姓名
137    str_sql varchar2(500);  --存储sql语句
138 begin
139    id:=1;
140    name:=Tom;
141    str_sql:=insert into t1 values(:1,:2);
142    --动态插入数据
143    execute immediate str_sql using id,name;  
144 exception
145    when others then
146    dbms_output.put_line(操作失败!);
147 end;
148 /
149 
150 select * from t1;
151 
152 运行结果:
153 PL/SQL 过程已成功完成。
154  select * from t1;
155 
156     ID NAME
157 ------ ------------
158      1 Tom
159      
160 
161 --6.动态sql查询总的数据条数
162 set serverout on
163 declare
164    v_id number:=1;
165    v_count number;
166    str_sql varchar2(500);
167 begin
168    str_sql:=select count(1) from t1 where id=:id;
169    --动态查询sql语句
170    execute immediate str_sql into v_count using v_id;
171    dbms_output.put_line(总的数据条数为:||v_count);
172 end;
173 /   
174 
175 --7.通过动态游标和动态sql一起使用查询多行数据
176 set serverout on
177 declare  
178   type emp_cur is ref cursor;
179   my_emp_cur emp_cur;
180   my_emp_rec emp%rowtype;
181    
182 begin
183   open my_emp_cur for select * from emp where deptno=:x using 30;
184   loop 
185     fetch my_emp_cur into my_emp_rec;
186     exit when my_emp_cur%notfound;
187     dbms_output.put_line(my_emp_rec.ename||||my_emp_rec.sal);
188   end loop;
189 end;
190 /
191 
192 运行结果:
193 ALLEN→1600
194 WARD→1250
195 MARTIN→1250
196 BLAKE→2850
197 TURNER→1500
198 JAMES→950
199 
200 PL/SQL 过程已成功完成。
201 
202 
203 --8.使用动态sql的DBMS_SQL包根据用户输入的表名、字段名及字段类型见表
204 set serverout on
205 declare
206    table_name2 varchar2(20); 
207    field1 varchar2(20);
208    datatype1 varchar2(20);
209    field2 varchar2(20);
210    datatype2 varchar2(20);
211    v_cursor number;
212    v_string varchar2(200);
213    v_row number;
214   
215 begin
216    table_name2:=t2;
217    field1:=id;
218    datatype1:=number;
219    field2:=name;
220    datatype2:=varchar2(20);
221    v_cursor:=dbms_sql.open_cursor;
222    v_string:=create table ||table_name2||(||field1|| ||datatype1||,||field2|| ||datatype2||);
223    dbms_sql.parse(v_cursor,v_string,dbms_sql.native);
224    v_row:=dbms_sql.execute(v_cursor);
225    dbms_sql.close_cursor(v_cursor);
226    dbms_output.put_line(v_row);
227 exception
228    when others then
229       dbms_sql.close_cursor(v_cursor);
230    raise;   
231 end;
232 /
233 
234 desc t2;
235 名称                                      是否为空? 类型
236 ----------------------------------------- -------- -------------
237 ID                                                 NUMBER
238 NAME                                               VARCHAR2(20)
239 
240 
241 --9.使用动态sql的DBMS_SQL包将表中t1中id=1的名称改为marry
242 set serverout on
243 declare
244    id number;
245    name varchar2(20);
246    v_cursor number;
247    v_string varchar2(200);
248    v_row number;
249   
250 begin
251    id:=1;
252    name:=Marry;
253    v_cursor:=dbms_sql.open_cursor;
254    v_string:=update t1 set name=:p_name where id=:p_id;
255    dbms_sql.parse(v_cursor,v_string,dbms_sql.native);
256    dbms_sql.bind_variable(v_cursor,:p_name,name);
257    dbms_sql.bind_variable(v_cursor,:p_id,id);
258    v_row:=dbms_sql.execute(v_cursor);
259    dbms_sql.close_cursor(v_cursor);
260 exception
261    when others then
262       dbms_sql.close_cursor(v_cursor);
263    raise;   
264 end;
265 /
266 
267 PL/SQL 过程已成功完成。
268 select * from t1;
269 
270 
271         ID NAME
272 ---------- ----------------
273          1 Marry
显示游标、动态游标,动态sql

三、隐式游标

技术分享
  1 一.隐式游标
  2 调用游标时:SQL%
  3 
  4 1.1 删除某个部门下的员工信息,如果该部门下没有员工,则删除部门表中的该部门信息
  5 
  6 set serverout on
  7 declare
  8   --动态输入删除的条件
  9   v_deptno emp.deptno%type:=&p_deptno;
 10   --定义接受受影响行数的变量
 11   v_count number;
 12 begin
 13   delete from emp where deptno=v_deptno;
 14   --接受受影响的行数赋值给变量
 15   v_count:=SQL%rowcount;
 16   
 17 --判断受影响的行数是否>0,如果为true就删除员工,否则删除部门信息
 18   if v_count>0 then
 19    dbms_output.put_line(部门编号为:||v_deptno||的员工信息已经被删除);
 20   else
 21     delete from dept where deptno=v_deptno; 
 22     if SQL%ROWCOUNT>0 then
 23     dbms_output.put_line(部门编号为:||v_deptno||的部门信息已经被删除);
 24     else 
 25      dbms_output.put_line(部门编号为:||v_deptno||数据没有找到);
 26    end if;
 27  end if;
 28 end;
 29 /
 30 
 31 1.2 动态游标
 32 --1.2.1 使用动态的弱类型游标实现查询员工信息和部门信息
 33 set serverout on
 34 declare
 35    --<1>定义弱类型游标
 36   TYPE TYPE_CURSOR_SCOTT IS REF CURSOR;
 37 
 38   --<2>定义游标变量
 39   c_scott TYPE_CURSOR_SCOTT;
 40 
 41   --<3>定义存储两个表数据的变量,相当于list
 42   e emp%rowtype; 
 43   d dept%rowtype;
 44 
 45   --<4>定义一个查询条件的变量
 46   v_deptno emp.deptno%type:=&p_deptno;
 47 
 48 begin
 49   --游标读取员工信息表
 50   --打开游标并将内容放入游标变量
 51   open c_scott 
 52     for
 53     select * from emp where deptno=v_deptno;
 54     dbms_output.put_line(员工编号--员工工资);
 55    loop
 56      fetch c_scott into e;
 57      exit when c_scott%notfound;
 58      dbms_output.put_line(e.empno||--||e.sal);
 59    end loop;
 60 
 61   --打开游标并将内容放入游标变量
 62   open c_scott 
 63     for
 64     select * from dept;
 65    dbms_output.put_line(部门编号--部门名字);
 66    --循环读取游标内容
 67    loop
 68      fetch c_scott into d;
 69      exit when c_scott%notfound;
 70      dbms_output.put_line(d.deptno||--||d.dname);
 71    end loop;
 72  
 73 --关闭游标
 74 close c_scott;
 75 end;
 76 /
 77 
 78 
 79 输入 p_deptno 的值:  10
 80 原值   13:   v_deptno emp.deptno%type:=&p_deptno;
 81 新值   13:   v_deptno emp.deptno%type:=10;
 82 7782--2450
 83 7839--5000
 84 7934--1300
 85 128--ccc
 86 143--新部门11
 87 144--啊啊啊
 88 10--统计1部
 89 20--RESEARCH
 90 30--销售7部
 91 40--OPERATIONS
 92 41--测试部
 93 42--产品研发部
 94 49--d1
 95 104--商业3部
 96 
 97 1.3 使用动态sql创建表
 98 set serverout on
 99 declare
100   --①.定义表名
101   table_name varchar2(20);
102   --②定义id列
103   id_name varchar2(20);
104   
105   --③定义id列的数据类型
106   idtype varchar2(20);
107   
108   --④定义name列
109   name varchar2(20);
110   
111   --⑤定义name列的数据类型
112   nametype varchar2(20);
113 
114   --⑥定义存放sql语句的变量
115   strsql varchar2(500);
116 begin
117   table_name:=t1;
118   id_name:=id;
119   idtype:=number;
120   name:=name;
121   nametype:=varchar2(20);
122 
123   strsql:=create table ||table_name
124 ||(||id_name|| ||idtype||,||name|| |nametype||);
125   dbms_output.put_line(sql语句:||strsql);
126 
127   --执行动态sql语句
128   execute immediate strsql;
129 exception
130   when others then
131     dbms_output.put_line(创建表失败!);
132 end;
133 /
134 
135 --1.4.动态sql插入数据
136 set serverout on
137 declare
138    id number;--输入序号
139    name varchar2(20);  --输入姓名
140    str_sql varchar2(500);  --存储sql语句
141 begin
142    id:=1;
143    name:=Tom;
144    str_sql:=insert into t1 values(:1,:2);
145    --动态插入数据
146    execute immediate str_sql using id,name;  
147 exception
148    when others then
149    dbms_output.put_line(操作失败!);
150 end;
151 /
152 
153 select * from t1;
154 
155 --1.5.动态sql查询总的数据条数(没有条件的)
156 set serverout on
157 declare
158    v_count number;
159    str_sql varchar2(500);
160 begin
161    str_sql:=select count(1) from t1;
162    --动态查询sql语句
163    execute immediate str_sql into v_count;
164    dbms_output.put_line(总的数据条数为:||v_count);
165 end;
166 / 
167 
168 --1.6.动态sql查询总的数据条数(有条件的)
169 set serverout on
170 declare
171    v_id number;
172    v_count number;
173    str_sql varchar2(500);
174 begin
175    v_id:=1;
176    str_sql:=select count(1) from t1 where id=:id;
177    --动态查询sql语句
178    execute immediate str_sql into v_count using v_id;
179    dbms_output.put_line(总的数据条数为:||v_count);
180 end;
181 / 
182 
183 --1.7 动态sql和动态游标结合查询多行数据
184 set serverout on
185 declare
186   --定义游标类型
187   TYPE c_type_emp IS REF CURSOR; 
188 
189   --定义游标类型变量
190   c_emp c_type_emp;
191  
192   --定义存储where条件的变量
193   v_deptno emp.deptno%type:=&p_deptno;
194 
195   --定义行数据类类型(表=集合)
196   list emp%rowtype;
197    
198 begin
199   --打开游标,同时使用动态sql,给占位符赋值
200   open c_emp
201     for select * from emp where deptno=:deptno
202     using v_deptno;
203   
204   --循环提取游标内容
205   loop
206      --先提取一行数据
207      fetch c_emp into list;
208      exit  when c_emp%notfound ;
209 
210      dbms_output.put_line(list.ename||-||list.deptno);
211   end loop;
212   
213   --关闭游标
214   close c_emp;
215 end;
216 /
217 
218 输入 p_deptno 的值:  30
219 原值    9:   v_deptno emp.deptno%type:=&p_deptno;
220 新值    9:   v_deptno emp.deptno%type:=30;
221 ALLEN-30
222 WARD-30
223 MARTIN-30
224 BLAKE-30
225 TURNER-30
226 JAMES-30
227     
隐式游标

 

7、游标

标签:

原文地址:http://www.cnblogs.com/holly8/p/5686756.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!