游标可以看做是数据的集合,可以通过游标获取其中的值,游标也可以看做是数据集合的指针,通过游标可以获取集合中的数据。
游标分为显示游标和隐式游标,它们都具有 %FOUND、%NOTFOUND、%ISOPEN、%ROWCOUNT四个属性。
- FOUND,NOTFOUND:表示是否找到数据。
- ISOPEN:判断游标是否打开。
- ROWCOUNT:返回SQL语句影响的行数,比如增删改。
名称 | 说明 | |
---|---|---|
系统游标(隐式游标) | 系统定义好的游标,一般在做DML操作时自动触发,单条的SELECT COL INTO V1 FROM TABLE也会产生一个系统游标 | |
用户游标(显式游标) | 静态游标 | 创建游标的SQL语句是固定的 |
动态游标 | 创建游标的SQL语句是动态的,带有参数或变量的 |
一、 游标的主要操作
-
创建游标:CURSOR 游标名 is 语句;
-
打开游标:OPEN 游标名;
-
遍历游标:FETCH 游标名 INTO 变量;
-
关闭游标:CLOSE 游标名;
注:如果游标是显示打开的,就要显示关闭。如果是隐式打开游标,自动遍历,就不用显示关闭了,但是如果是显示打开游标的话需要些游标指针移动的语句,才能遍历。
CURSOR emp_cs is SELECT * FROM emp WHERE deptno=10;-- 定义一个静态游标
OPEN emp_cs;-- 显示打开游标
-- 游标指针向前移动一条记录,并把记录存储到变量中
FETCH emp_cs INTO v_emp_row;
-- 游标%NOTFOUND判断游标是否已经到底的属性
IF emp_cs%NOTFOUND THEN
EXIT;
END IF;
-- 如果游标的状态是打开状态 游标%ISOPEN判断游标打开的状态
IF emp_cs%ISOPEN THEN
-- 关闭游标 CLOSE 游标,用来关闭打开的游标
CLOSE emp_cs;
END IF;
二、 静态游标
declare
-- 定义一个静态游标,因为SQL语句是固定的,没有变数的
CURSOR emp_cs is SELECT * FROM emp WHERE deptno=10;
v_emp_row emp%ROWTYPE;-- emp表行对象类型
begin
-- 显示打开游标,此时游标指针指向的是游标的头部
OPEN emp_cs;
LOOP
-- 游标指针向前移动一条记录,并把记录存储到变量中
FETCH emp_cs INTO v_emp_row;
-- 如果游标指针已经到了游标的底部,则退出循环
IF emp_cs%NOTFOUND THEN
EXIT;
END IF;
dbms_output.put_line(v_emp_row.empno||'-'||v_emp_row.ename);
END LOOP;
-- 如果游标的状态是打开状态
IF emp_cs%ISOPEN THEN
-- 关闭游标
CLOSE emp_cs;
END IF;
end;
三、 动态游标
动态游标的优点是游标是灵活的,可以使用变量和参数,甚至SQL语句都可以是一个变量,动态游标需要先定义一个游标类型,然后通过游标类型定义一个动态游标变量,在打开游标的同时指定游标的实际SQL语句。
declare
v_deptno emp.deptno%TYPE;-- 部门编号列
-- 先定义一个动态游标类型
TYPE dync IS REF CURSOR;
-- 用动态游标类型定义一个动态游标变量
emp_cs dync;
v_emp_row emp%ROWTYPE;
BEGIN
SELECT deptno INTO v_deptno FROM emp WHERE empno=7782;
dbms_output.put_line('deptno='||v_deptno);
-- 动态游标的SQL语句是动态的,不确定的
OPEN emp_cs FOR SELECT * FROM emp WHERE deptno=v_deptno;
LOOP
FETCH emp_cs INTO v_emp_row;
IF emp_cs%NOTFOUND THEN
EXIT;
END IF;
dbms_output.put_line(v_emp_row.empno||'-'||v_emp_row.ename);
END LOOP;
IF emp_cs%ISOPEN THEN
dbms_output.put_line('游标关闭');
CLOSE emp_cs;
END IF;
end;
四、 隐式游标
隐式游标是系统定义好的,在做DML操作时会触发,一般需要得到的是影响到行数的信息:SQL%ROWCOUNT。
declare
BEGIN
INSERT INTO emp(empno) VALUES(2);
dbms_output.put_line('隐式游标影响的行数:'||SQL%ROWCOUNT);