游标

 

 

范例:验证ROWCOUNT

DECLARE

v_count NUMBER ;

BEGIN

SELECT COUNT(*) INTO v_count FROM dept ; -- 只返回一行结果

DBMS_OUTPUT.put_line('SQL%ROWCOUNT = '|| SQL%ROWCOUNT) ;

END ;

/

 

范例:验证ROWCOUNT,增加新数据返回行数

DECLARE

BEGIN

INSERT INTO dept(deptno,dname,loc) VALUES (90,'MLDN','北京') ;

DBMS_OUTPUT.put_line('SQL%ROWCOUNT = '|| SQL%ROWCOUNT) ;

END ;

/

 

范例:单行隐式游标

DECLARE

v_empRow emp%ROWTYPE ; -- 保存emp每行记录

BEGIN

SELECT * INTO v_empRow FROM emp WHERE empno=7369 ;

IF SQL%FOUND THEN -- 发现数据

DBMS_OUTPUT.put_line('雇员姓名:' || v_empRow.ename || ',职位:' || v_empRow.job) ;

END IF ;

END ;

/

 

范例:更新多行记录

BEGIN

UPDATE emp SET sal=sal*1.2 ;

IF SQL%FOUND THEN -- 发现数据

DBMS_OUTPUT.put_line('更新记录行数:' ||SQL%ROWCOUNT) ;

ELSE

DBMS_OUTPUT.put_line('没有记录被修改!') ;

END IF ;

END ;

/

 

范例:定义显式游标

DECLARE

CURSOR cur_emp IS SELECT * FROM emp ;

v_empRow emp%ROWTYPE ;

BEGIN

IF cur_emp%ISOPEN THEN -- 游标已经打开

NULL ;

ELSE -- 游标未打开

OPEN cur_emp ; -- 打开游标

END IF ;

FETCH cur_emp INTO v_empRow ; -- 取出游标当前行数据

WHILE cur_emp%FOUND LOOP -- 判断是否有数据

DBMS_OUTPUT.put_line(cur_emp%ROWCOUNT || '、雇员姓名:' || v_empRow.ename || ',职位:' || v_empRow.job || ',工资:' || v_empRow.sal) ;

FETCH cur_emp INTO v_empRow ; -- 把游标指向下一行

END LOOP ;

CLOSE cur_emp ; -- 关闭游标

END ;

/

范例:修改游标定义

CURSOR cur_emp RETURN emp%ROWTYPE IS SELECT * FROM emp ;

范例:没有打开游标直接进行操作

DECLARE

CURSOR cur_emp IS SELECT * FROM emp ;

v_empRow emp%ROWTYPE ;

BEGIN

LOOP -- 没有打开游标

FETCH cur_emp INTO v_empRow ; -- 取出游标当前行数据

EXIT WHEN cur_emp%NOTFOUND ; -- 如果没有找到数据则退出循环

DBMS_OUTPUT.put_line(cur_emp%ROWCOUNT || '、雇员姓名:' || v_empRow.ename) ;

END LOOP ;

CLOSE cur_emp ; -- 关闭游标

EXCEPTION

WHEN INVALID_CURSOR THEN

DBMS_OUTPUT.put_line('程序出错。SQL CODE = ' || SQLCODE || 'SQLERRM = ' || SQLERRM) ;

END ;

/

 

范例:使用LOOP循环输出游标

DECLARE

CURSOR cur_emp IS SELECT * FROM emp ;

v_empRow emp%ROWTYPE ;

BEGIN

IF cur_emp%ISOPEN THEN -- 游标打开

NULL ;

ELSE -- 游标未打开

OPEN cur_emp ; -- 打开游标

END IF ;

LOOP

FETCH cur_emp INTO v_empRow ; -- 取出游标当前行数据

EXIT WHEN cur_emp%NOTFOUND ; -- 如果没有找到数据则退出循环

DBMS_OUTPUT.put_line(cur_emp%ROWCOUNT || '、雇员姓名:' || v_empRow.ename || ',职位:' || v_empRow.job || ',工资:' || v_empRow.sal) ;

END LOOP ;

CLOSE cur_emp ; -- 关闭游标

END ;

/

范例:使用FOR循环操作游标

DECLARE

CURSOR cur_emp IS SELECT * FROM emp ;

BEGIN

FOR emp_row IN cur_emp LOOP

DBMS_OUTPUT.put_line(cur_emp%ROWCOUNT || '、雇员姓名:' || emp_row.ename || ',职位:' || emp_row.job || ',工资:' || emp_row.sal) ;

END LOOP ;

END ;

/

范例:查询数据

BEGIN

FOR v_dept IN (SELECT deptno,dname,loc FROM dept) LOOP

DBMS_OUTPUT.put_line('部门编号:' || v_dept.deptno || ',名称:' || v_dept.dname || ',位置:' || v_dept.loc) ;

END LOOP ;

END ;

/

范例:将游标数据保存在索引表中

DECLARE

CURSOR cur_emp IS

SELECT * FROM emp ; -- 定义游标取得emp表数据

TYPE emp_index IS TABLE OF emp%ROWTYPE INDEX BY PLS_INTEGER ;-- 定义索引表数据类型为emp行结构

v_emp emp_index ; -- 定义索引表变量

BEGIN

FOR emp_row IN cur_emp LOOP -- 利用循环取得每一行记录

v_emp(emp_row.empno) := emp_row ; -- 将雇员编号作为索引表下标

END LOOP ;

DBMS_OUTPUT.put_line('雇员编号:' || v_emp(7369).empno || ',姓名:' || v_emp(7369).ename || ',职位:' || v_emp(7369).job) ;

END ;

/

 

范例:动态SELECT中使用游标

DECLARE

v_lowsal emp.sal%TYPE := &inputlowsal ;

v_highsal emp.sal%TYPE := &inputhighsal ;

CURSOR cur_emp IS SELECT * FROM emp WHERE sal BETWEEN v_lowsal AND v_highsal ;

BEGIN

FOR emp_row IN cur_emp LOOP

DBMS_OUTPUT.put_line(cur_emp%ROWCOUNT || '、雇员姓名:' || emp_row.ename || ',职位:' || emp_row.job || ',工资:' || emp_row.sal) ;

END LOOP ;

END ;

/

 

范例:定义参数游标

DECLARE

CURSOR cur_emp (p_dno emp.deptno%TYPE) IS SELECT * FROM emp WHERE deptno=p_dno;

BEGIN

FOR emp_row IN cur_emp(&inputDeptno) LOOP

DBMS_OUTPUT.put_line(cur_emp%ROWCOUNT || '、雇员姓名:' || emp_row.ename || ',职位:' || emp_row.job || ',工资:' || emp_row.sal) ;

END LOOP ;

END ;

/

 

范例:使用嵌套表接收游标数据

DECLARE

TYPE dept_nested IS TABLE OF dept%ROWTYPE ; -- 定义dept的嵌套表类型

v_dept dept_nested ;

CURSOR cur_dept IS SELECT * FROM dept ; -- 定义游标

BEGIN

IF cur_dept%ISOPEN THEN -- 游标已经打开

NULL ;

ELSE -- 游标未打开

OPEN cur_dept ; -- 打开游标

END IF ;

FETCH cur_dept BULK COLLECT INTO v_dept ; -- 保存整个游标

CLOSE cur_dept ; -- 关闭游标

FOR x IN v_dept.FIRST .. v_dept.LAST LOOP

DBMS_OUTPUT.put_line('部门编号:' || v_dept(x).deptno || ',部门名称:' || v_dept(x).dname

|| ',部门位置:' || v_dept(x).loc) ;

END LOOP ;

END ;

/

 

范例:取得部分数据保存在数组之中

DECLARE

TYPE dept_varray IS VARRAY(2) OF dept%ROWTYPE ;

v_dept dept_varray ;

v_rows NUMBER := 2 ; -- 每次提取的行数

v_count NUMBER := 1 ; -- 每次少显示1条记录

CURSOR cur_dept IS SELECT * FROM dept ; -- 定义游标

BEGIN

IF cur_dept%ISOPEN THEN -- 游标已经打开

NULL ;

ELSE -- 游标未打开

OPEN cur_dept ; -- 打开游标

END IF ;

FETCH cur_dept BULK COLLECT INTO v_dept LIMIT v_rows ;-- 保存指定行数

CLOSE cur_dept ; -- 关闭游标

FOR x IN v_dept.FIRST .. (v_dept.LAST - v_count) LOOP

DBMS_OUTPUT.put_line('部门编号:' || v_dept(x).deptno || ',部门名称:' || v_dept(x).dname

|| ',部门位置:' || v_dept(x).loc) ;

END LOOP ;

END ;

/

 

范例:一次上涨所有人的工资,工资上涨原则如下:

· 10部门上涨15%

· 20部门上涨22%

· 30部门上涨39%

但是每一个雇员的工资上限为5000,即上涨5000之后就不能再涨了。

DECLARE

CURSOR cur_emp IS SELECT * FROM emp ; -- emp表游标数据

BEGIN

FOR emp_row IN cur_emp LOOP -- 循环游标的每一行数据

IF emp_row.deptno = 10 THEN

IF emp_row.sal*1.15 < 5000 THEN

UPDATE emp SET sal=sal*1.15 WHERE empno=emp_row.empno ;

ELSE

UPDATE emp SET sal=5000 WHERE empno=emp_row.empno ;

END IF ;

ELSIF emp_row.deptno = 20 THEN

IF emp_row.sal*1.22 < 5000 THEN

UPDATE emp SET sal=sal*1.22 WHERE empno=emp_row.empno ;

ELSE

UPDATE emp SET sal=5000 WHERE empno=emp_row.empno ;

END IF ;

ELSIF emp_row.deptno = 30 THEN

IF emp_row.sal*1.39 < 5000 THEN

UPDATE emp SET sal=sal*1.39 WHERE empno=emp_row.empno ;

ELSE

UPDATE emp SET sal=5000 WHERE empno=emp_row.empno ;

END IF ;

ELSE

NULL ;

END IF ;

END LOOP ;

EXCEPTION

WHEN others THEN

DBMS_OUTPUT.put_line('SQLCODE = ' || SQLCODE) ;

DBMS_OUTPUT.put_line('SQLERRM = ' || SQLERRM) ;

ROLLBACK ;

END ;

/

范例:为游标数据增加行级锁

CURSOR cur_emp IS SELECT * FROM emp WHERE deptno=10 FOR UPDATE OF sal,comm. ;

范例:创建不等待游标

DECLARE

CURSOR cur_emp IS SELECT * FROM emp WHERE deptno=10 FOR UPDATE NOWAIT;

BEGIN

FOR emp_row IN cur_emp LOOP

UPDATE emp SET sal=9999 WHERE empno=emp_row.empno ;

END LOOP ;

END ;

/

范例:使用WHERE CURRENT OF子句

DECLARE

CURSOR cur_emp IS SELECT * FROM emp WHERE deptno=10 FOR UPDATE OF sal,comm ;

BEGIN

FOR emp_row IN cur_emp LOOP

UPDATE emp SET sal=9999 WHERE CURRENT OF cur_emp ;

END LOOP ;

END ;

/

范例:使用游标删除数据

DECLARE

CURSOR cur_emp IS SELECT * FROM emp WHERE deptno=10 FOR UPDATE OF sal, comm ;

BEGIN

FOR emp_row IN cur_emp LOOP

DELETE FROM emp WHERE CURRENT OF cur_emp ;

END LOOP ;

END ;

/

 

1 创建一个新的游标使用FOR UPDATE”,采用多表查询

DECLARE

CURSOR cur_emp IS

SELECT e.ename,e.job,e.sal,d.dname,d.loc

FROM emp e,dept d

WHERE e.deptno=10 AND d.deptno=e.deptno

FOR UPDATE ;

BEGIN

FOR emp_row IN cur_emp LOOP

UPDATE emp SET sal=9999 WHERE CURRENT OF cur_emp ;

END LOOP ;

END ;

/

 

创建一个新的游标使用FOR UPDATE OF ..”,采用多表查询

DECLARE

CURSOR cur_emp IS

SELECT e.ename,e.job,e.sal,d.dname,d.loc

FROM emp e,dept d

WHERE e.deptno=10 AND d.deptno=e.deptno

FOR UPDATE OF sal ;

BEGIN

FOR emp_row IN cur_emp LOOP

UPDATE emp SET sal=9999 WHERE CURRENT OF cur_emp ;

END LOOP ;

END ;

/

 

范例:定义一个游标类型,此游标类型为dept类型

DECLARE

TYPE dept_ref IS REF CURSOR RETURN dept%ROWTYPE ; -- 定义游标类型

cur_dept dept_ref ; -- 定义游标变量

v_deptRow dept%ROWTYPE ; -- 定义行类型

BEGIN

OPEN cur_dept FOR SELECT * FROM dept ; -- 打开游标

LOOP

FETCH cur_dept INTO v_deptRow ; -- 取得游标数据

EXIT WHEN cur_dept%NOTFOUND ; -- 如果没有数据则退出

DBMS_OUTPUT.put_line('部门名称:' || v_deptRow.dname || ',部门位置:' || v_deptRow.loc) ;

END LOOP ; 

CLOSE cur_dept ; -- 关闭游标

END ;

/

范例:设置错误的数据结构

DECLARE

TYPE dept_ref IS REF CURSOR ; -- 定义游标类型

cur_dept dept_ref ; -- 定义游标变量

v_deptRow dept%ROWTYPE ; -- 定义行类型

BEGIN

OPEN cur_dept FOR SELECT * FROM emp ;-- 打开游标,类型错误

LOOP

FETCH cur_dept INTO v_deptRow ; -- 取得游标数据

EXIT WHEN cur_dept%NOTFOUND ; -- 如果没有数据则退出

DBMS_OUTPUT.put_line('部门名称:' || v_deptRow.dname || ',部门位置:' || v_deptRow.loc) ;

END LOOP ;

CLOSE cur_dept ; -- 关闭游标

EXCEPTION

WHEN ROWTYPE_MISMATCH THEN

DBMS_OUTPUT.put_line('游标数据类型不匹配异常。SQL CODE = ' || SQLCODE || 'SQLERRM = ' || SQLERRM) ;

END ;

/

 

范例:定义弱类型游标变量

DECLARE

TYPE cursor_ref IS REF CURSOR ; -- 定义游标类型

cur_var cursor_ref ; -- 定义游标变量

v_deptRow dept%ROWTYPE ; -- 定义行类型

v_empRow emp%ROWTYPE ; -- 定义行类型

BEGIN

OPEN cur_var FOR SELECT * FROM dept ; -- 打开游标

LOOP

FETCH cur_var INTO v_deptRow ; -- 取得游标数据

EXIT WHEN cur_var%NOTFOUND ; -- 如果没有数据则退出

DBMS_OUTPUT.put_line('1、部门名称:' || v_deptRow.dname || ',部门位置:' || v_deptRow.loc) ;

END LOOP ;

CLOSE cur_var ;

OPEN cur_var FOR SELECT * FROM emp WHERE deptno=10 ; -- 打开游标

LOOP

FETCH cur_var INTO v_empRow ; -- 取得游标数据

EXIT WHEN cur_var%NOTFOUND ; -- 如果没有数据则退出

DBMS_OUTPUT.put_line('2、雇员姓名:' || v_empRow.ename || ',雇员职位:' || v_empRow.job) ;

END LOOP ;

CLOSE cur_dept ; -- 关闭游标

END ;

/

原文地址:https://www.cnblogs.com/doudouxiaoye/p/5804112.html