Oracle中游标的用法

什么是游标?

①从表中检索出结果集,从中每次指向一条记录进行交互的机制。

②关系数据库中的操作是在完整的行集合上执行的。

由 SELECT 语句返回的行集合包括满足该语句的 WHERE 子句所列条件的所有行。由该语句返回完整的行集合叫做结果集。

应用程序,尤其是互动和在线应用程序,把完整的结果集作为一个单元处理并不总是有效的。

这些应用程序需要一种机制来一次处理一行或连续的几行。而游标是对提供这一机制的结果集的扩展。

游标是通过游标库来实现的。游标库是常常作为数据库系统或数据访问 API 的一部分而得以实现的软件,用来管理从数据源返回的数据的属性(结果集)。这些属性包括并发管理、在结果集中的位置、返回的行数,以及是否能够在结果集中向前和/或向后移动(可滚动性)。

游标跟踪结果集中的位置,并允许对结果集逐行执行多个操作,在这个过程中可能返回至原始表,也可能不返回至原始表。

换句话说,游标从概念上讲基于数据库的表返回结果集。

由于它指示结果集中的当前位置 ,就像计算机屏幕上的光标指示当前位置一样,“游标”由此得名。

游标有什么作用?

①指定结果集中特定行的位置。

②基于当前的结果集位置检索一行或连续的几行。

③在结果集的当前位置修改行中的数据。

④对其他用户所做的数据更改定义不同的敏感性级别。

⑤可以以编程的方式访问数据库。

一、游标:

1、概念:

游标的本质是一个结果集resultset,主要用来临时存储从数据库中提取出来的数据块。

二、游标的分类:

1、显式游标:

由用户定义,需要的操作:定义游标、打开游标、提取数据、关闭游标,主要用于对查询语句的处理。

属性:%FOUND %NOTFOUND %ISOPEN %ROWCOUNT

Example:打印emp表的员工信息

DECLARE
 CURSOR emp_cursor IS SELECT empno,ename,job FROM emp;
 v_empno emp.empno%TYPE;
 v_name emp.ename%TYPE;
 v_job emp.job%TYPE;
BEGIN
 OPEN emp_cursor;
 LOOP
 FETCH emp_cursor INTO v_empno,v_name,v_job;
 DBMS_OUTPUT.PUT_LINE('员工号为:'||v_empno||'姓名是'||v_name||'职位:'||v_job);
 EXIT WHEN emp_cursor%NOTFOUND;
 END LOOP;
 CLOSE emp_cursor;
END;

这里严格按照显示游标的书写规则:DECLARE emp_cursor定义游标OPEN emp_cursor打开游标FETCH emp_cursor INTO...提取数据CLOSE emp_cursor关闭游标,因为提取出来的数据属于多行,所以通过loop循环打印即可。

Example2:检验游标是否打开,如果打开显示提取行数

DECLARE
 CURSOR emp_cursor IS SELECT empno,ename,job FROM emp;
 v_empno emp.empno%TYPE;
 v_name emp.ename%TYPE;
 v_job emp.job%TYPE;
BEGIN
 OPEN emp_cursor;
 LOOP
  FETCH emp_cursor INTO v_empno,v_name,v_job;
  EXIT WHEN emp_cursor%NOTFOUND;
 END LOOP;
 IF emp_cursor%ISOPEN THEN
 DBMS_OUTPUT.PUT_LINE('游标已打开');
 DBMS_OUTPUT.PUT_LINE('读取了'||emp_cursor%ROWCOUNT||'行');
 ELSE
 DBMS_OUTPUT.PUT_LINE('游标没有打开');
 END IF;
 CLOSE emp_cursor;
END;

-- 游标(光标cursor)
--在写Java程序中有集合的概念, 那么在pl/sql中也会用到多条记录, 这时候我们就要用到游标, 游标可以存储查询返回的多条数据。
-- 语法:cursor 游标名(参数 数据类型,参数 数据类型) is select 语句;
-- 列如 cursor c1 is select ename from emp;
-- 游标使用步骤
-- 打开游标:open c1
-- 取一行游标值 fetch c1 into pjob;(取一行数据到变量中)
-- 关闭游标 close c1
-- 游标结束方式 exit when c1%notfound

-- 查询姓名和工资
declare
cursor vrows is select * from emp;
vrow emp%Rowtype;
begin
open vrows;
loop
fetch vrows into vrow;
exit when vrows%notfound;
dbms_output.put_line('姓名:'||vrow.ename||' '||'工资:'||vrow.sal);
end loop;
close vrows;
end;

-- 指定部门下的员工工资
declare
cursor deptSal(dno number) is select * from emp where deptno=dno;
dep emp%rowtype;
begin
open deptSal(10);
loop
fetch deptSal into dep;
exit when deptSal%notfound;
dbms_output.put_line('员工姓名:'||dep.ename||' '||'工资:'||dep.sal);
end loop;
close deptSal;
end;
-- 引用系统游标
declare
vrows sys_refcursor; -- 引用系统游标
vrow emp%rowtype; -- 记录一行数据
begin
open vrows for select * from emp;
loop
fetch vrows into vrow;
exit when vrows%notfound;
dbms_output.put_line('姓名:'||vrow.ename||' '||'工资:'||vrow.sal);
end loop;
close vrows;
end;

-- 使用for循环遍历游标
declare
-- 申明游标
cursor vrows is select * from emp;
begin
for vrow in vrows loop
dbms_output.put_line('姓名为:'||vrow.ename||'工资为:'||vrow.sal);
end loop;
end;

-- 按员工的工种长工资,总裁1000元,经理长800元其, 他人员长400元
declare
cursor vrows is select * from emp;
vrow emp%rowtype;
begin
open vrows;
loop
fetch vrows into vrow;
exit when vrows%notfound;
if vrow.job='PRESIDENT' then
update emp set sal=sal+1000 where empno=vrow.empno;
elsif vrow.job='MANAGER' then
update emp set sal=sal+800 where empno=vrow.empno;
else
update emp set sal=sal+400 where empno=vrow.empno;
end if;
dbms_output.put_line('姓名为:'||vrow.ename||'工资为:'||vrow.sal);
end loop;
close vrows;
end;

2、隐式游标:由系统定义并为它创建工作区域,并且隐式的定义打开提取关闭,隐式游标的游标名就是'SQL',属性和显示游标相同,主要用于对单行select语句或dml操作进行处理。Example:又用户输入员工号修改员工工资如成功则打印输出成功标志。

3、参数游标:

在定义游标时加入参数的游标,可以配合游标for循环快速找到需要的数据。这里先讲一下游标for循环

A、游标FOR循环:

隐含的执行了打开提取关闭数据,代码精简很多。Expression:

FOR table_record IN table_cursor LOOP

  STATEMENT;

END LOOP;

三、使用游标修改数据的注意事项

1、使用游标修改数据时,为防止他人在自己操作数据时对数据进行修改,oracle提供for update子句进行加锁。

同时在你使用update或delete时,必须使用where current of+name_cursor语句,以及在最后记得提交。如果是级联操作则可以使用for update of 来进行相关表的加锁。

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

声明游标;CURSOR cursor_name IS select_statement

--For 循环游标
--(1)定义游标
--(2)定义游标变量
--(3)使用for循环来使用这个游标
declare
--类型定义
cursor c_job
is
select empno,ename,job,sal
from emp
where job='MANAGER';
--定义一个游标变量v_cinfo c_emp%ROWTYPE ,该类型为游标c_emp中的一行数据类型
c_row c_job%rowtype;
begin
for c_row in c_job loop
dbms_output.put_line(c_row.empno||'-'||c_row.ename||'-'||c_row.job||'-'||c_row.sal);
end loop;
end;



--Fetch游标
--使用的时候必须要明确的打开和关闭

declare
--类型定义
cursor c_job
is
select empno,ename,job,sal
from emp
where job='MANAGER';
--定义一个游标变量
c_row c_job%rowtype;
begin
open c_job;
loop
--提取一行数据到c_row
fetch c_job into c_row;
--判读是否提取到值,没取到值就退出
--取到值c_job%notfound 是false
--取不到值c_job%notfound 是true
exit when c_job%notfound;
dbms_output.put_line(c_row.empno||'-'||c_row.ename||'-'||c_row.job||'-'||c_row.sal);
end loop;
--关闭游标
close c_job;
end;

--1:任意执行一个update操作,用隐式游标sql的属性%found,%notfound,%rowcount,%isopen观察update语句的执行情况。
begin
update emp set ENAME='ALEARK' WHERE EMPNO=7469;
if sql%isopen then
dbms_output.put_line('Openging');
else
dbms_output.put_line('closing');
end if;
if sql%found then
dbms_output.put_line('游标指向了有效行');--判断游标是否指向有效行
else
dbms_output.put_line('Sorry');
end if;
if sql%notfound then
dbms_output.put_line('Also Sorry');
else
dbms_output.put_line('Haha');
end if;
dbms_output.put_line(sql%rowcount);
exception
when no_data_found then
dbms_output.put_line('Sorry No data');
when too_many_rows then
dbms_output.put_line('Too Many rows');
end;
declare
empNumber emp.EMPNO%TYPE;
empName emp.ENAME%TYPE;
begin
if sql%isopen then
dbms_output.put_line('Cursor is opinging');
else
dbms_output.put_line('Cursor is Close');
end if;
if sql%notfound then
dbms_output.put_line('No Value');
else
dbms_output.put_line(empNumber);
end if; dbms_output.put_line(sql%rowcount);
原文地址:https://www.cnblogs.com/mxh168/p/13965760.html