目录
游标是一个什么样的概念
游标有哪些种类
游标的使用方法
使用游标时的注意事项
注:由于在学习游标的时候兼顾的学习了存储过程,所以这里针对游标的建立均在存储过程中建立。
游标是一个什么样的概念
游标是一个私有的sql工作区,简单的说就是受到影响的数据都会存在这里面,比如执行完update语句但是没有commit,那这条修改过但是没有提交的数据是放在一个虚表中的,这个虚表就是游标。
游标有哪些种类
游标一共分为显示游标、隐式游标、还有带参数的游标三种,下面我们一一这三种类型的游标进行练习。
游标的使用方法
这里声明几个关键词与游标的属性。
-
cursor 游标名【游标,在declare中创建游标时使用它修饰】
-
fetch 游标名【表示提取游标里的数据】
-
open 游标名【表示打开游标】
-
close 游标名【表示关闭游标】
-
游标名%ROWCOUNT【表示受影响的数据一共有多少行】
-
游标名%NOTFOUND【返回true和false,表示是否没有数据】
-
游标名%FOUND【返回true和false,表示是否有数据】
-
游标名%ISOPEN【返回true和false,表示游标是否打开】
显示游标
需要的操作:定义游标、打开游标、提取数据、关闭游标;主要用于对查询语句的处理,对根据条件查询出来的数据进行一条一条处理。
sql窗口
CREATE OR REPLACE PROCEDURE TEST_1
IS
cursor emp_cursor is select empno,ename,job FROM emp;
--定义游标
v_empno emp.empno%TYPE;
v_empname emp.ename%TYPE;
v_empjob emp.job%TYPE;
--定义行变量
BEGIN
open emp_cursor;
--打开游标
fetch emp_cursor into v_empno,v_empname,v_empjob;
--提取数据,正常应该放在循环里循环提取,这里只提取了一次所以只有一条数据。
DBMS_OUTPUT.PUT_LINE('读取了'||emp_cursor%ROWCOUNT||'行数据');
close emp_cursor;
--关闭游标
END TEST_1;
Test窗口
-- Created on 2019/4/22 by ADMINISTRATOR
declare
begin
dbms_output.put_line('执行存储过程Begin');
TEST_1();
--即使没有参数也要写括号!
dbms_output.put_line('执行存储过程End');
end;
隐式游标
系统自动创建游标,游标名是sql,主要用于直接对单行的数据增删改的操作。由于开始我们提到游标里的数据就是一些受到影响的数据但是还没有被提交,隐式游标就是直接使用dml语句后没有提交的数据。
sql窗口
CREATE OR REPLACE PROCEDURE TEST_1 IS
BEGIN
UPDATE emp SET sal = sal + 500 WHERE empno = '7839';
--直接更改数据,系统创建游标
IF SQL%FOUND THEN--如果有受影响的数据
DBMS_OUTPUT.PUT_LINE('成功修改');
COMMIT;--提交
ELSE
DBMS_OUTPUT.PUT_LINE('修改失败');
ROLLBACK;--回滚
END IF;
END TEST_1;
Test窗口
-- Created on 2019/4/22 by ADMINISTRATOR
declare
begin
dbms_output.put_line('执行存储过程Begin');
TEST_1();
dbms_output.put_line('执行存储过程End');
end;
参数游标
在定义游标时加入参数,可以配合for循环快速找到数据。隐含的执行了打开提取关闭,代码相对精简。for循环的结构请看下面的plsql的语法
sql窗口
CREATE OR REPLACE PROCEDURE TEST_1 IS
CURSOR emp_cursor IS SELECT empno, ename, job FROM emp;
BEGIN
FOR emp_record IN emp_cursor LOOP
DBMS_OUTPUT.PUT_LINE('员工号:' || emp_record.empno || '员工姓名' ||emp_record.ename || '员工职位' || emp_record.job);
END LOOP;
--FOR emp_record IN (SELECT empno,ename,job FROM emp) LOOP
-- DBMS_OUTPUT.PUT_LINE('员工号:' || emp_record.empno || '员工姓名' ||emp_record.ename || '员工职位' || emp_record.job);
-- END LOOP;
--相比第一种更加精简,直接引入子查询。
END TEST_1;
Test窗口
-- Created on 2019/4/22 by ADMINISTRATOR
declare
begin
dbms_output.put_line('执行存储过程Begin');
TEST_1();
dbms_output.put_line('执行存储过程End');
end;
使用游标时的注意事项
-
使用游标修改数据的时候最后要记得提交
-
如果是级联操作可以使用for update锁表
-
在修改时必须使用where current of 语句。