Orace游标:
一、游标简介:
使用游标,我们可以对具体操作数据,比如查询的结果,对行,列数据进行更加细致的处理。以及对其他DML操作进行判断等操作;
二、显示游标:
1.静态的指定变量类型:
SQL> declare cursor cu_emp is select empno,ename,sal from emp; 2 e_no number; 3 e_name varchar2(10); 4 e_sal number; 5 begin 6 open cu_emp; 7 fetch cu_emp into e_no, e_name, e_sal; 8 while cu_emp%found loop 9 dbms_output.put_line('编号:'||e_no||',姓名:'||e_name||',基本薪资:'||e_sal); 10 fetch cu_emp into e_no, e_name, e_sal; 11 end loop; 12 close cu_emp; 13 end; 14 / 编号:7369,姓名:SMITH,基本薪资:800 编号:7499,姓名:ALLEN,基本薪资:1600 编号:7521,姓名:WARD,基本薪资:1250 编号:7566,姓名:JONES,基本薪资:2975 编号:7654,姓名:MARTIN,基本薪资:1250 编号:7698,姓名:BLAKE,基本薪资:2850 编号:7782,姓名:CLARK,基本薪资:2450 编号:7788,姓名:SCOTT,基本薪资:3000 编号:7839,姓名:KING,基本薪资:5000 编号:7844,姓名:TURNER,基本薪资:1500 编号:7876,姓名:ADAMS,基本薪资:1100 编号:7900,姓名:JAMES,基本薪资:950 编号:7902,姓名:FORD,基本薪资:3000 编号:7934,姓名:MILLER,基本薪资:1300 PL/SQL 过程已成功完成。
2.动态指定变量类型:
SQL> declare cursor cu_emp is select empno,ename,sal from emp; 2 e_no emp.empno%type; 3 e_name emp.ename%type; 4 e_sal emp.sal%type; 5 begin 6 open cu_emp; 7 fetch cu_emp into e_no, e_name, e_sal; 8 while cu_emp%found loop 9 dbms_output.put_line('编号:'||e_no||',姓名:'||e_name||',基本薪资:'||e_sal); 10 fetch cu_emp into e_no, e_name, e_sal; 11 end loop; 12 close cu_emp; 13 end; 14 / 编号:7369,姓名:SMITH,基本薪资:800 编号:7499,姓名:ALLEN,基本薪资:1600 编号:7521,姓名:WARD,基本薪资:1250 编号:7566,姓名:JONES,基本薪资:2975 编号:7654,姓名:MARTIN,基本薪资:1250 编号:7698,姓名:BLAKE,基本薪资:2850 编号:7782,姓名:CLARK,基本薪资:2450 编号:7788,姓名:SCOTT,基本薪资:3000 编号:7839,姓名:KING,基本薪资:5000 编号:7844,姓名:TURNER,基本薪资:1500 编号:7876,姓名:ADAMS,基本薪资:1100 编号:7900,姓名:JAMES,基本薪资:950 编号:7902,姓名:FORD,基本薪资:3000 编号:7934,姓名:MILLER,基本薪资:1300 PL/SQL 过程已成功完成。
3.行类型:%rowtype:
SQL> declare cursor cu_emp is select * from emp; 2 e emp%rowtype; 3 begin 4 open cu_emp; 5 fetch cu_emp into e; 6 while cu_emp%found loop 7 dbms_output.put_line('编号:'||e.empno||',姓名:'||e.ename||',基本薪资:'||e.sal); 8 fetch cu_emp into e; 9 end loop; 10 close cu_emp; 11 end; 12 / 编号:7369,姓名:SMITH,基本薪资:800 编号:7499,姓名:ALLEN,基本薪资:1600 编号:7521,姓名:WARD,基本薪资:1250 编号:7566,姓名:JONES,基本薪资:2975 编号:7654,姓名:MARTIN,基本薪资:1250 编号:7698,姓名:BLAKE,基本薪资:2850 编号:7782,姓名:CLARK,基本薪资:2450 编号:7788,姓名:SCOTT,基本薪资:3000 编号:7839,姓名:KING,基本薪资:5000 编号:7844,姓名:TURNER,基本薪资:1500 编号:7876,姓名:ADAMS,基本薪资:1100 编号:7900,姓名:JAMES,基本薪资:950 编号:7902,姓名:FORD,基本薪资:3000 编号:7934,姓名:MILLER,基本薪资:1300 PL/SQL 过程已成功完成。
上面的也可以查询带条件:
SQL> declare cursor cu_emp is select * from emp where sal > 2000 and sal < 3000; 2 e emp%rowtype; 3 begin 4 open cu_emp; 5 fetch cu_emp into e; 6 while cu_emp%found loop 7 dbms_output.put_line('编号:'||e.empno||',姓名:'||e.ename||', 基本薪资:'||e.sal); 8 fetch cu_emp into e; 9 end loop; 10 close cu_emp; 11 end; 12 / 编号:7566,姓名:JONES,基本薪资:2975 编号:7698,姓名:BLAKE,基本薪资:2850 编号:7782,姓名:CLARK,基本薪资:2450 PL/SQL 过程已成功完成。
4.游标的其他循环方式:
SQL> declare cursor c is select * from emp; 2 v_emp c%rowtype; 3 begin 4 open c; 5 fetch c into v_emp; 6 dbms_output.put_line(v_emp.ename); 7 close c; 8 end; 9 / SMITH PL/SQL 过程已成功完成。
//cursor c is xx 声明一个游标,但是并不会真真正正的从数据库取数据,open c才取数据
//fetch c 拿出第一个数据,并且游标指向下一行数据;fetch开始是指在第一条数据上,每fetch下,就指向下一条;
loop循环:
SQL> declare cursor c is select * from emp; 2 v_emp c%rowtype; 3 begin 4 open c; 5 loop 6 fetch c into v_emp; 7 exit when(c%notfound); 8 dbms_output.put_line(v_emp.ename); 9 end loop; 10 close c; 11 end; 12 / SMITH ALLEN WARD ... PL/SQL 过程已成功完成。
while循环:
SQL> declare cursor c is select * from emp; 2 v_emp c%rowtype; 3 begin 4 open c; 5 fetch c into v_emp; 6 while(c%found) loop 7 dbms_output.put_line(v_emp.ename); 8 fetch c into v_emp; 9 end loop; 10 close c; 11 end; 12 / SMITH ALLEN ... PL/SQL 过程已成功完成。
for循环:
SQL> declare cursor c is select * from emp; 2 begin 3 for v_emp in c loop 4 dbms_output.put_line(v_emp.ename); 5 end loop; 6 end; 7 / SMITH ALLEN ... PL/SQL 过程已成功完成。
//不需要声明v_emp,for循环自动声明;
//不需要open游标、close游标,for循环开始自动打开游标,循环结束自动关闭游标;最不容易出错。使用最多。
5.带参数的游标:
SQL> select ename, sal from emp where deptno=30 and job='CLERK'; ENAME SAL ---------- ---------- JAMES 950 SQL> declare cursor c(v_deptno emp.deptno%type, v_job emp.job%type) 2 is select ename,sal from emp where deptno = v_deptno and job = v_job; 3 begin 4 for v_temp in c(30, 'CLERK') loop 5 dbms_output.put_line(v_temp.ename); 6 end loop; 7 end; 8 / JAMES PL/SQL 过程已成功完成。
6.可更新的游标:
declare cursor c is select * from emp2 for update; begin for v_temp in c loop if(v_temp.sal < 2000) then update emp2 set sal = sal*2 where current of c; elsif (v_temp.sal = 5000) then delete from emp2 where current of c; end if; end loop; commit; end;
三、隐式游标:
SQL> begin 2 if sql%isopen then 3 dbms_output.put_line('sql游标以打开'); 4 else 5 dbms_output.put_line('sql游标未打开'); 6 end if; 7 end; 8 / sql游标未打开 PL/SQL 过程已成功完成。
SQL> declare e_count number; 2 begin 3 select count(*) into e_count from emp; 4 dbms_output.put_line('游标捕获的记录数:'||sql%rowcount); 5 end; 6 / 游标捕获的记录数:1 PL/SQL 过程已成功完成。
%rowcount : 新增、修改影响的记录数会返回;
SQL> begin 2 update emp2 set sal = 808 where ename='SMITH'; 3 if sql%rowcount=1 then 4 dbms_output.put_line('已更新'); 5 else 6 dbms_output.put_line('未更新'); 7 end if; 8 end; 9 / 已更新 PL/SQL 过程已成功完成。
SQL> begin 2 update emp2 set sal = 800 where ename='SMITH'; 3 if sql%found then 4 dbms_output.put_line('已更新'); 5 else 6 dbms_output.put_line('未更新'); 7 end if; 8 end; 9 / 已更新 PL/SQL 过程已成功完成。
四、动态游标
前面说的都是静态游标:开始声明就定死了;静态的;
1.强类型动态游标:
有个需求,老大(job为PRESIDENT)在的时候打印老大的信息,不然打印emp表的所有信息:
SQL> declare type emptype is ref cursor return emp%rowtype; 2 cu_emp emptype; 3 e_count number; 4 e emp%rowtype; 5 begin 6 select count(*) into e_count from emp where job = 'PRESIDENT'; 7 if e_count=0 then 8 open cu_emp for select * from emp; 9 else 10 open cu_emp for select * from emp where job = 'PRESIDENT'; 11 end if; 12 fetch cu_emp into e; 13 while cu_emp%found loop 14 dbms_output.put_line('编号:'||e.empno||',姓名:'||e.ename||',基本薪资:'||e.sal); 15 fetch cu_emp into e; 16 end loop; 17 close cu_emp; 18 end; 19 / 编号:7839,姓名:KING,基本薪资:5000 PL/SQL 过程已成功完成。
2.弱类型动态游标:
需求:老大在的时候,输出老大信息;老大不在的时候,输出薪资等级信息;
SQL> declare type customType is ref cursor; 2 e_count number; 3 e emp%rowtype; 4 s salgrade%rowType; 5 cType customType; 6 begin 7 select count(*) into e_count from emp where job='PRESIDENT'; 8 if e_count=0 then 9 open cType for select * from salgrade; 10 fetch cType into s; 11 while cType%found loop 12 dbms_output.put_line('等级:'||s.grade||',最低薪资:'||s.losal||',最高薪资:'||s.hisal); 13 fetch cType into s; 14 end loop; 15 close cType; 16 else 17 open cType for select * from emp where job='PRESIDENT'; 18 fetch cType into e; 19 while cType%found loop 20 dbms_output.put_line('编号:'||e.empno||',姓名:'||e.ename||',基本薪资:'||e.sal); 21 fetch cType into e; 22 end loop; 23 close cType; 24 end if; 25 end; 26 / 编号:7839,姓名:KING,基本薪资:5000 PL/SQL 过程已成功完成。