一、游标语法概念和案例
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 /