作者:gqk


游标 CURSOR:

一、游标概述:

游标(cursor)是数据库系统在内存中开设的一个数据缓冲区,存放SQL语句的执行结果。

每个游标都有一个名字,用户可以用SQL语句逐一从游标中获取记录,并赋给变量做进一步处理。

作用:用于定位结果集的行 和 遍历结果集。

二、游标分类:

  • 显式游标:在前述程序中用到的SELECT...INTO...查询语句,一次只能从数据库中提取一行数据,对于这种形式的查询和DML操作,系统都会使用一个隐式游标
  • 隐式游标:但是如果要提取多行数据,就要由程序员定义一个显式游标,并通过与游标有关的语句进行处理。显式游标对应一个返回结果为多行多列的SELECT语句。

三:显示游标:

处理显示游标需要的四个步骤:

  • 定义游标:就是定义一个游标的名称,以及与其对应的SELECT语句,形式如下

    • CURSOR 游标名称 IS select_statement
  • 打开游标 :open 游标变量(不能重复打开游标)
    • 打开游标时,SELECT语句的查询结果就被传送到了游标工作区。 
  • 提取数据 :fetch 游标变量 into 变量1,变量2,……
    • 提取操作必须在打开游标之后进行。
  • 关闭游标:close 游标变量 

  显式游标打开后,必须显式地关闭。游标一旦关闭,游标占用的资源就被释放,游标变成无效,必须重新打开才能使用。

--查询输出所有员工的编号,姓名,工资:(当执行fetch时提取数据指针下移一行)

DECLAREv_empid employees.employee_id%TYPE;v_name  employees.last_name%TYPE;v_salary employees.salary%TYPE;CURSOR emp_cursor IS SELECT employee_id,last_name,salary FROM employees WHERE department_id=90;
BEGIN       OPEN emp_cursor;FETCH emp_cursor INTO v_empid,v_name,v_salary;--默认指向第一行FETCH emp_cursor INTO v_empid,v_name,v_salary;FETCH emp_cursor INTO v_empid,v_name,v_salary;dbms_output.put_line('编号:' || v_empid);dbms_output.put_line('姓名:' || v_name);dbms_output.put_line('工资:' || v_salary);  CLOSE emp_cursor;
END;

四:游标的四个属性

  游标变量%found:当最近一次读记录时成功返回,则值为TRUE
   游标变量%notfound:同上,求反
   游标变量%isopen:判断游标是否已经打开
   游标变量%rowcount:返回已从游标中读取的记录数  

  --查询输出所有员工的编号,姓名,工资

  loop循环

DECLAREv_empid employees.employee_id%TYPE;v_name  employees.last_name%TYPE;v_salary employees.salary%TYPE;CURSOR emp_cursor IS SELECT employee_id,last_name,salary FROM employees;
BEGIN       OPEN emp_cursor;LOOP      FETCH emp_cursor INTO v_empid,v_name,v_salary;EXIT WHEN emp_cursor%NOTFOUND;--读取最后一次失败后跳出循环dbms_output.put_line('编号:' || v_empid);dbms_output.put_line('姓名:' || v_name);dbms_output.put_line('工资:' || v_salary);  dbms_output.put_line('--------------------'); END LOOP;CLOSE emp_cursor;
END;

  while 循环

DECLAREv_empid employees.employee_id%TYPE;v_name  employees.last_name%TYPE;v_salary employees.salary%TYPE;CURSOR emp_cursor IS SELECT employee_id,last_name,salary FROM employees;
BEGIN       OPEN emp_cursor;FETCH emp_cursor INTO v_empid,v_name,v_salary;WHILE emp_cursor%FOUND LOOP         dbms_output.put_line('编号:' || v_empid);dbms_output.put_line('姓名:' || v_name);dbms_output.put_line('工资:' || v_salary);  dbms_output.put_line('--------------------');FETCH emp_cursor INTO v_empid,v_name,v_salary; END LOOP;CLOSE emp_cursor;
END;

  --查询输出所有员工的编号,姓名,工资(PLSQL表类型)

DECLARETYPE emp_table_type IS TABLE OF employees%ROWTYPEINDEX BY BINARY_INTEGER;e emp_table_type;CURSOR emp_cursor IS SELECT * FROM employees;
BEGIN       OPEN emp_cursor;FETCH emp_cursor BULK COLLECT INTO e;FOR i IN 1..e.COUNT LOOPdbms_output.put_line('编号:' || e(i).employee_id);dbms_output.put_line('姓名:' || e(i).last_name);dbms_output.put_line('工资:' || e(i).salary); dbms_output.put_line('--------------------');END LOOP;CLOSE emp_cursor;
END;

 --查询输出所有员工的编号,姓名,工资(通过limit控制提取的数据量)每次提取6条数据

DECLARETYPE emp_table_type IS TABLE OF employees%ROWTYPEINDEX BY BINARY_INTEGER;e emp_table_type;v_count NUMBER := 1;CURSOR emp_cursor IS SELECT * FROM employees;
BEGIN       OPEN emp_cursor;LOOPdbms_output.put_line('第' || v_count || '次FETCH');FETCH emp_cursor BULK COLLECT INTO e LIMIT 6;FOR i IN 1..e.COUNT LOOPdbms_output.put_line('编号:' || e(i).employee_id);dbms_output.put_line('姓名:' || e(i).last_name);dbms_output.put_line('工资:' || e(i).salary); dbms_output.put_line('--------------------');END LOOP;EXIT WHEN emp_cursor%NOTFOUND;v_count := v_count + 1;       END LOOP;CLOSE emp_cursor;
END;

 --查询输出某个部门的员工的编号,姓名,工资(参数化游标) 

DECLAREv_empid employees.employee_id%TYPE;v_name  employees.last_name%TYPE;v_salary employees.salary%TYPE;CURSOR emp_cursor(p_deptid employees.department_id%TYPE) IS SELECT employee_id,last_name,salary FROM employeesWHERE department_id=p_deptid;
BEGIN       OPEN emp_cursor(50);LOOP      FETCH emp_cursor INTO v_empid,v_name,v_salary;EXIT WHEN emp_cursor%NOTFOUND;dbms_output.put_line('编号:' || v_empid || ',姓名:' || v_name || ',工资:' || v_salary);                      END LOOP;CLOSE emp_cursor; dbms_output.put_line('----------------------');  OPEN emp_cursor(90);LOOP      FETCH emp_cursor INTO v_empid,v_name,v_salary;EXIT WHEN emp_cursor%NOTFOUND;dbms_output.put_line('编号:' || v_empid || ',姓名:' || v_name || ',工资:' || v_salary);                      END LOOP;CLOSE emp_cursor;
END;

  五:游标for循环:

 PL/SQL中提供了游标for循环语句,可以自动的执行游标的open,fetch,close语句和循环语句的功能,当进入循环时,游标for循环语句自动打开游标,并提取第一行数据,提取

  提取完成后自动进入下一个提取,提取完成后自动关闭游标:

--查询输出所有员工的编号,姓名,工资

DECLARE CURSOR emp_cursor IS SELECT *FROM employees;
BEGIN       FOR e IN emp_cursor LOOPdbms_output.put_line(e.employee_id||','||e.last_name||','||e.salary);END LOOP;
END;

--查询输出所有员工的编号,姓名,工资(带参数)

DECLARE CURSOR emp_cursor(p_deptid employees.department_id%TYPE) IS SELECT *FROM employeesWHERE department_id=p_deptid;
BEGIN       FOR e IN emp_cursor(90) LOOPdbms_output.put_line(e.employee_id||','||e.last_name||','||e.salary);END LOOP;
END;

--查询输出所有员工的编号,姓名,工资(最精简写法)

DECLARE BEGIN       FOR e IN (SELECT * FROM employees) LOOPdbms_output.put_line(e.employee_id||','||e.last_name||','||e.salary);END LOOP;
END;

 --输出每个部门的部门编号,部门名称以及这个部门的下属员工的编号,姓名,工资
/*
10 nec
   100,tom,2400
   101,jack,17000
20 ge
   102,rose,2600
   xxx,xxx,xxx
   xxx,xxx,xxx
40 hsw
   xxx,xxx,xxx
*/

DECLARECURSOR dept_cursor ISSELECT * FROM departments;CURSOR emp_cursor(p_deptid NUMBER) ISSELECT * FROM employeesWHERE  department_id=p_deptid;
BEGINFOR d IN dept_cursor LOOPdbms_output.put_line(d.department_id || ' ' || d.department_name);FOR e IN emp_cursor(d.department_id) LOOPdbms_output.put_line('    ' || e.employee_id || ',' || e.last_name || ',' || e.salary);END LOOP;END LOOP;
END;

/*
隐式游标:固定名称SQL
游标四个属性:
SQL%FOUND:如果操作有影响的行,就为TRUE,否则为FALSE
SQL%NOTFOUND:求反
SQL%ISOPEN:在隐式游标中,取值永远为FALSE
SQL%ROWCOUNT:操作影响的行数
必须在事务结束之前读取游标属性,只能读取最近的一次DML操作的游标状态
*/
--用户输入一个任意的部门编号,更新这个部门的员工的工资
--如果有员工被更新,输出“更新成功,有XX个员工被更新”
--如果没有任何员工被更新,输出“这个部门不存在,没有任何员工被更新”
DECLAREv_deptid NUMBER := &input;
BEGINUPDATE employeesSET    salary = salary + 1WHERE  department_id = v_deptid;IF SQL%FOUND THENdbms_output.put_line('更新成功,有' || SQL%ROWCOUNT || '个员工被更新');ELSEdbms_output.put_line('这个部门不存在,没有任何员工被更新');END IF;COMMIT;
END;

  --通过游标去更新员工的工资,如果工资低于5000块,则把工资改为5000

DECLARECURSOR emp_cursor ISSELECT * FROM new_emp FOR UPDATE;
BEGINFOR e IN emp_cursor LOOPIF e.salary<5000 THENUPDATE new_emp SET salary=5000 WHERE CURRENT OF emp_cursor;END IF;END LOOP;
END;

  --通过游标删除工资=5000的员工

DECLARECURSOR emp_cursor ISSELECT * FROM new_emp FOR UPDATE;
BEGINFOR e IN emp_cursor LOOPIF e.salary=5000 THENDELETE FROM new_emp WHERE CURRENT OF emp_cursor;END IF;END LOOP;
END;

 --游标变量(动态游标)
--用户输入一个字母,输入E,输出所有员工姓名,如果输入D,输出所有部门的名称

DECLAREv_cmd CHAR(1) := '&input';v_name VARCHAR2(50);--声明自定义的游标变量类型--TYPE c_type IS REF CURSOR;--声明游标变量--c c_type;c SYS_REFCURSOR;--代替TYPE c_type IS REF CURSOR
BEGINIF v_cmd='E' THENdbms_output.put_line('员工姓名'); OPEN c FOR SELECT last_name FROM employees;ELSIF v_cmd='D' THENdbms_output.put_line('部门名称'); OPEN c FOR SELECT department_name FROM departments;ELSEdbms_output.put_line('输入无效'); RETURN;END IF;LOOPFETCH c INTO v_name;EXIT WHEN c%NOTFOUND;dbms_output.put_line(v_name);END LOOP;CLOSE c;
END;

转载于:https://www.cnblogs.com/520gqk/p/9862859.html

Oracle游标 CURSOR实例详解相关推荐

  1. oracle 记录给游标,Oracle游标 CURSOR实例详解

    一.游标概述: 游标(cursor)是数据库系统在内存中开设的一个数据缓冲区,存放SQL语句的执行结果. 每个游标都有一个名字,用户可以用SQL语句逐一从游标中获取记录,并赋给变量做进一步处理. 作用 ...

  2. oracle几种例外,Oracle例外用法实例详解

    本文实例讲述了Oracle例外用法.分享给大家供大家参考,具体如下: 一.例外分类 oracle将例外分为预定义例外.非预定义例外和自定义例外三种. 1).预定义例外用于处理常见的oracle错误. ...

  3. java 获取oracle表结构_Java导出oracle表结构实例详解

    Java导出oracle表结构实例详解 发布于 2020-7-20| 复制链接 摘记:  Java导出oracle表结构实例详解最近用到的,因为plsql是收费的,不让用,找了很多方法终于发现了这个. ...

  4. [转载]Oracle触发器用法实例详解

    本文实例讲述了Oracle触发器用法.分享给大家供大家参考,具体如下: 一.触发器简介 触发器的定义就是说某个条件成立的时候,触发器里面所定义的语句就会被自动的执行. 因此触发器不需要人为的去调用,也 ...

  5. oracle 触发器用法,Oracle触发器用法实例详解

    本文实例讲述了Oracle触发器用法.分享给大家供大家参考,具体如下: 一.触发器简介 触发器的定义就是说某个条件成立的时候,触发器里面所定义的语句就会被自动的执行. 因此触发器不需要人为的去调用,也 ...

  6. 在oracle中游标的操作,Oracle中的游标和函数详解

    Oracle中的游标和函数详解 1.游标 游标是一种 PL/SQL 控制结构:可以对 SQL 语句的处理进行显示控制,便于对表的行数据 逐条进行处理. 游标并不是一个数据库对象,只是存留在内存中. 操 ...

  7. oracle大对象实例_Oracle解析复杂json的方法实例详解

    问题背景: 当前在Oracle数据库(11G之前的版本)解析json没有可以直接使用的系统方法,网上流传的PLSQL脚本大多也只可以解析结构较单一的json串,对于结构复杂的json串还无法解析.如此 ...

  8. oracle out参数查询,Oracle的out参数实例详解

    Oracle的out参数实例详解 一 概念 1.一般来讲,存储过程和存储函数的区别在于存储函数可以有一个返回值:而存储过程没有返回值. 2.过程和函数都可以通过out指定一个或多个输出行.我们可以利用 ...

  9. oracle中表空间实例,oracle的表空间实例详解

    oracle 的表空间实例详解 查询表空间 SELECT UPPER(F.TABLESPACE_NAME) "表空间名", D.TOT_GROOTTE_MB "表空间大小 ...

  10. oracle身份证的正则表达式,Oracle 正则表达式实例详解

    Oracle 正则表达式实例详解 FORM开发中的按行拆分需求:拆分后的行要有规律,并按前后层次排序 需求分析如下: 现有行: 2 , 2.1 , 2.2 , 2.3 3 2.1.1,2.1.2,2. ...

最新文章

  1. 微信小程序 require module exports 的使用
  2. 真正的 AI 内行盛会!智源大会带你刷新“世界第一”记录!
  3. Socket 阻塞模式和非阻塞模式
  4. 702:Crossing River (贪心)
  5. 【转】visual studio 2010失败或.net framework 4.0 0xc8000247错误解决
  6. 蓝奏云文件上传php源码_蓝奏云客户端 v0.3.1,第三方蓝奏网盘电脑版
  7. jquery 延迟加载代码_延迟加载是一种代码气味
  8. 重启php-fpm的方法
  9. 这个超时问题花了我两周才解决!
  10. UISearchBar--改变内部输入框的背景颜色
  11. 基于GPU的大规模图计算系统与应用
  12. 网站被移动运营方屏蔽怎么办?
  13. Windows10无法修改图标字体和菜单栏字体问题 —— regedit注册表修改
  14. 岳不群认识独孤九剑吗?
  15. 《前沿》(Frontiers)系列英文学术期介绍
  16. 垂杨柳中学2021年高考成绩查询时间,实力入选!朝阳这几所学校上榜啦丨校园直通车(2021年第4期)...
  17. C3P0配置错误导致的连接关闭问题
  18. 2016第二届美亚杯全国电子数据取证大赛团队赛write up
  19. WIN10 windows installar 启动类型灰色不可更改
  20. QGIS|三步拥有全国县级行政区划

热门文章

  1. 【渝粤教育】国家开放大学2018年秋季 2780T遗传与育种 参考试题
  2. 23种设计模式(十九)数据结构之组合模式
  3. 求解偏微分方程开源有限元软件deal.II学习--Step 13
  4. LeetCode 150. 逆波兰表达式求值(Evaluate Reverse Polish Notation) 24
  5. MySQL操作(备份很重要)
  6. JS实现new关键字的功能
  7. 第二阶段:4.商业需求文档MRD:5.PRD-原型图
  8. [No000083]文件与文件夹操作
  9. 模板---函数模板,类模板等
  10. 初学JAVA随记——循环语句的几个要点