Oracle cursor

--游标分2种类型: --静态游标:结果集已经存在(静态定义)的游标,分为隐式和显示游标

  1. 隐式游标:所有DML语句为隐式游标,通过隐式游标属性可以获取SQL语句信息
  2. 显示游标:用户显示声明的游标,即指定结果集,当查询返回结果超过一定行时,就需要一个显示游标

--REF 游标:动态关联结果集的临时对象

  1. -强类型:带return类型
  2. -弱类型: 不带return类型

--隐式游标 --在PL/SQL中编写的每条SQL 语句实际上都是隐匿游标。通过在DML操作后使用SQL%ROWCOUNT属性,可以 --知道语句所改变的行数(INSERT ,UPDATE,DELETE)返回理新行数,SELECT 返回查询行数.
--显示游标 --语法:CURSOR 游标名称 ([参数列表,]) [RETURN 返回值类型] IS 子查询(SELECT _statement) --第一步:声明游标: CURSOR 游标名 IS SELECT 。。使用CURSOR定义 --第二步:打开游标     使用OPEN     OPEN 游标名 --第三步:提取游标     使用FETCH  游标 INTO 变量 --第四步:关闭游标 CLOSE 游标名 --显式游标属性:   %FOUND     找到是否找到数据,有数据TRUE,没有则FALSE   %ISOPEN    判断游标是否打开,打开则返回TRUE,没有打开则返回FALSE   %NOTFOUND  返回FETCH ...INTO...是否有数据如果没有返回TRUN,有则为FALSE   %ROWCOUNT  返回执行FETCH 语句所返回的行数,初始为0,每执行一行则%ROWCOUNT增加1 --隐式游标属性: SQL%FOUND     找到是否找到数据,有数据TRUE,没有则FALSE   SQL%ISOPEN    判断游标是否打开,打开则返回TRUE,没有打开则返回FALSE   SQL%NOTFOUND  返回FETCH ...INTO...是否有数据如果没有返回TRUN,有则为FALSE   SQL%ROWCOUNT  返回执行FETCH 语句所返回的行数,初始为0,每执行一行则%ROWCOUNT增加1

隐式游标:

--验证SQL%ROWCOUNT

DECLARE
  v_count         NUMBER;
BEGIN
  SELECT COUNT(*) INTO v_count FROM dept; --只返回一行结果
  dbms_output.put_line(‘SQL%ROWCOUNT= ‘|| SQL%ROWCOUNT);
END;

结果:SQL%ROWCOUNT= 1

--验证SLQ%ROWCOUNT并返回行数

DECLARE
BEGIN
   INSERT INTO dept(deptno,dname,loc)VALUES(90,‘qqqq‘,‘北京‘);
     dbms_output.put_line(‘SQL%ROWCOUNT= ‘|| SQL%ROWCOUNT);
END;

结果:SQL%ROWCOUNT= 1

--单行隐式游标

DECLARE
   v_empRow         emp%ROWTYPE;
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;

结果:员工姓名: SMITH职位: CLERK

--多行隐式游标

DECLARE
BEGIN
  UPDATE EMP SET SAL = SAL * 1.2;
  IF SQL%FOUND THEN
    --发现数据
    DBMS_OUTPUT.PUT_LINE(‘更新行数‘ || SQL%ROWCOUNT);
  ELSE
    DBMS_OUTPUT.PUT_LINE(‘更新行数‘ || SQL%ROWCOUNT);
  END IF;
END;

结果:更新行数14

--显示游标 --定义游标例1:

DECLARE
 CURSOR emp_cur IS
 SELECT empno,ename FROM emp;                    --定义游标
 v_id     emp.empno%TYPE;              --定义变量ID
 v_name    emp.ename%TYPE;
BEGIN
  OPEN emp_cur ;                          --打开游标
  FETCH emp_cur INTO v_id,v_name;    ---提示取游标
  LOOP
    EXIT WHEN emp_cur%notFOUND;                     --判断是否还有数据
    dbms_output.put_line(‘员工编号‘||v_id||‘,员工姓名:‘||v_name);
    FETCH emp_cur INTO v_id,v_name;    ---提示取游标
  END LOOP;
  CLOSE emp_cur;                  --关闭游标
END;

结果:

员工编号7369,员工姓名:SMITH
员工编号7499,员工姓名:ALLEN
员工编号7521,员工姓名:WARD
员工编号7566,员工姓名:JONES
员工编号7654,员工姓名:MARTIN
员工编号7698,员工姓名:BLAKE
员工编号7782,员工姓名:CLARK
员工编号7788,员工姓名:SCOTT
员工编号7839,员工姓名:KING
员工编号7844,员工姓名:TURNER
员工编号7876,员工姓名:ADAMS
员工编号7900,员工姓名:JAMES
员工编号7902,员工姓名:FORD
员工编号7934,员工姓名:MILLER

--定义游标例2:

DECLARE
  V_NAME  VARCHAR2(50); --定义变量姓名
  V_DNAME VARCHAR2(50); --定义变量部门名称
  CURSOR CUR_E IS --定义游标
    SELECT ENAME, DNAME FROM EMP, DEPT WHERE EMP.DEPTNO = DEPT.DEPTNO;
BEGIN
  OPEN CUR_E; --打开游标
  LOOP
    --使用循环来读取游标
    FETCH CUR_E
      INTO V_NAME, V_DNAME; --提取游标
    EXIT WHEN CUR_E%NOTFOUND; --判断游标是否还有内容
    DBMS_OUTPUT.PUT_LINE(CUR_E%ROWCOUNT || ‘  员工姓名:‘ || V_NAME || ‘ 部门名称:‘ ||
                         V_DNAME);                            --输出内容

  END LOOP;
  CLOSE CUR_E; --关闭游标
END;

结果:

程序结果:
1  员工姓名:SMITH 部门名称:RESEARCH
2  员工姓名:ALLEN 部门名称:SALES
3  员工姓名:WARD 部门名称:SALES
4  员工姓名:JONES 部门名称:RESEARCH
5  员工姓名:MARTIN 部门名称:SALES
6  员工姓名:BLAKE 部门名称:SALES
7  员工姓名:CLARK 部门名称:ACCOUNTING
8  员工姓名:SCOTT 部门名称:RESEARCH
9  员工姓名:KING 部门名称:ACCOUNTING
10  员工姓名:TURNER 部门名称:SALES
11  员工姓名:ADAMS 部门名称:RESEARCH
12  员工姓名:JAMES 部门名称:SALES
13  员工姓名:FORD 部门名称:RESEARCH
14  员工姓名:MILLER 部门名称:ACCOUNTING

另一种指定变量类型:

DECLARE
  V_EMPNAME EMP.ENAME%TYPE;
  V_DNAME   DEPT.DNAME%TYPE;
  CURSOR EMP_CUR IS
    SELECT E.ENAME, D.DNAME FROM EMP E, DEPT D WHERE E.DEPTNO = D.DEPTNO;
BEGIN
  OPEN EMP_CUR;
  LOOP
    FETCH EMP_CUR
      INTO V_EMPNAME, V_DNAME;
    EXIT WHEN EMP_CUR%NOTFOUND;
    DBMS_OUTPUT.PUT_LINE(‘员工姓名 :‘ || V_EMPNAME || ‘,部门名称 :‘ || V_DNAME);
  END LOOP;
  CLOSE EMP_CUR;
END;

结果同上

--定义游标例3:

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(‘员工姓名: ‘ || V_EMPROW.ENAME || ‘,职位: ‘ ||
                         V_EMPROW.JOB || ‘ ,工资‘ || V_EMPROW.SAL);
    FETCH CUR_EMP
      INTO V_EMPROW;
  END LOOP;
  CLOSE CUR_EMP;
END;

结果:

员工姓名: SMITH,职位: CLERK ,工资800
员工姓名: ALLEN,职位: SALESMAN ,工资1600
员工姓名: WARD,职位: SALESMAN ,工资1250
员工姓名: JONES,职位: MANAGER ,工资2975
员工姓名: MARTIN,职位: SALESMAN ,工资1250
员工姓名: BLAKE,职位: MANAGER ,工资2850
员工姓名: CLARK,职位: MANAGER ,工资2450
员工姓名: SCOTT,职位: ANALYST ,工资3000
员工姓名: KING,职位: PRESIDENT ,工资5000
员工姓名: TURNER,职位: SALESMAN ,工资1500
员工姓名: ADAMS,职位: CLERK ,工资1100
员工姓名: JAMES,职位: CLERK ,工资950
员工姓名: FORD,职位: ANALYST ,工资3000
员工姓名: MILLER,职位: CLERK ,工资1300

--使用FOR循环

DECLARE
CURSOR cur_emp IS SELECT * FROM emp;
BEGIN
  FOR emp_row IN cur_emp LOOP
    DBMS_OUTPUT.PUT_LINE(‘员工姓名: ‘ || emp_row.ENAME || ‘,职位: ‘ ||
                         emp_row.JOB || ‘ ,工资‘ || emp_row.SAL);
     END LOOP;
END;

结果同上

--使用FOR循环操作游标不仅代码简单,而且可以将游标的状态交给系统去完成,尽量使用FOR循环为主

--定义游标例4:使用游标UPDATE数据 --公司上市,决定给员工涨工资,入职年限超过1年加100,1000元封顶 --第一种 直接将计算的结果进行判断

DECLARE
  V_ID       EMP.EMPNO%TYPE;
  V_HIREDATE EMP.HIREDATE%TYPE;
  CURSOR EMP_CUR IS
    SELECT EMPNO, HIREDATE FROM EMP;
BEGIN
  OPEN EMP_CUR;
  LOOP
    FETCH EMP_CUR
      INTO V_ID, V_HIREDATE;
    EXIT WHEN EMP_CUR%NOTFOUND;
    IF (TO_CHAR(SYSDATE, ‘yyyy‘) - TO_CHAR(V_HIREDATE, ‘yyyy‘)) * 100 < 1000 THEN
      UPDATE EMP
         SET SAL = SAL +
                   (TO_CHAR(SYSDATE, ‘yyyy‘) - TO_CHAR(V_HIREDATE, ‘yyyy‘)) * 100
       WHERE EMPNO = V_ID;
      DBMS_OUTPUT.PUT_LINE(‘工资增加成功‘);
      COMMIT;
    ELSE
      UPDATE EMP SET SAL = SAL + 1000 WHERE EMPNO = V_ID;
      DBMS_OUTPUT.PUT_LINE(‘工资增加成功‘);
      COMMIT;
    END IF;
  END LOOP;
  CLOSE EMP_CUR;
EXCEPTION
  WHEN OTHERS THEN
    DBMS_OUTPUT.PUT_LINE(‘数据异常‘);
    ROLLBACK;
END;

--第二种通过一个变量判断

DECLARE
  V_ID       EMP.EMPNO%TYPE; --定义员工编号ID
  V_HIREDATE EMP.HIREDATE%TYPE; --定义员工入职日期变量
  V_SAL      EMP.SAL%TYPE; --定义计算每个员工要涨工资的总数变量
  CURSOR CUR_EMP IS
    SELECT EMPNO, HIREDATE --定义游标查询员工ID和入职日期
      FROM EMP;
BEGIN
  IF CUR_EMP%ISOPEN THEN
    --判断游标是否打开
    NULL; --打开了就什么也不做
  ELSE
    OPEN CUR_EMP; --没有打开就打开游标
  END IF;
  LOOP
    FETCH CUR_EMP
      INTO V_ID, V_HIREDATE;
    EXIT WHEN CUR_EMP%NOTFOUND;
    V_SAL := (TO_CHAR(SYSDATE, ‘yyyy‘) - TO_CHAR(V_HIREDATE, ‘yyyy‘)) * 100;
    IF V_SAL < 1000 THEN
      --判断是否小于1000
      UPDATE EMP SET SAL = SAL + V_SAL WHERE EMPNO = V_ID;
      COMMIT;
    ELSE
      --大于1000
      UPDATE EMP SET SAL = SAL + 1000 WHERE EMPNO = V_ID;
      COMMIT;
    END IF;
  END LOOP;
  CLOSE CUR_EMP; --关闭游标
EXCEPTION
  WHEN OTHERS THEN
    DBMS_OUTPUT.PUT_LINE(‘数据异常‘);
    ROLLBACK; --出现异常 就回滚
END;

--定义游标例5 --在动态SELECT中使用游标

DECLARE
  V_LOWSAL EMP.SAL%TYPE := &LOWSAL;
  V_HISAL  EMP.SAL%TYPE := &HISSAL;
  CURSOR CUR_EMP IS
    SELECT * FROM EMP WHERE SAL BETWEEN V_LOWSAL AND V_HISAL;
BEGIN
  FOR EMP_ROW IN CUR_EMP LOOP
    DBMS_OUTPUT.PUT_LINE(‘员工姓名: ‘ || EMP_ROW.ENAME || ‘,职位: ‘ ||
                         EMP_ROW.JOB || ‘ ,工资‘ || EMP_ROW.SAL);
  END LOOP;
END;

--REF动态游标 TYPE 类型名 IS REF CURSOR [RETURN]数据类型 游标名 类型名       OPEN 游标名 FOR 查询语句 --强类型:带RETURN

DECLARE
  TYPE REF_EMP IS REF CURSOR RETURN EMP%ROWTYPE; --定义一个REF动态游标,并返回类型
  CUR_EMP REF_EMP; --定义一个变量类型是上面的REF动态游标也称游标变量
  V_EMP   EMP%ROWTYPE; --定义一个变量,类型和REF游标返回类型相同,行类型
BEGIN
  OPEN CUR_EMP FOR
    SELECT * FROM EMP; --打开游标,并关联查询语句
  LOOP
    FETCH CUR_EMP
      INTO V_EMP; --提取游标数据
    EXIT WHEN CUR_EMP%NOTFOUND;
    DBMS_OUTPUT.PUT_LINE(CUR_EMP%ROWCOUNT||‘  员工编号:‘ || V_EMP.EMPNO || ‘ 员工姓名:‘ || V_EMP.ENAME);
  END LOOP;
  CLOSE CUR_EMP;
END;

--弱类型:不带RETURN

DECLARE
  TYPE REF_EMP IS REF CURSOR; --定义一个REF动态游标,并返回类型
  CUR_EMP REF_EMP; --定义一个变量类型是上面的REF动态游标也称游标变量
  V_EMP   EMP%ROWTYPE; --定义一个变量,类型和REF游标返回类型相同,行类型
  V_DEPT  DEPT%ROWTYPE; --定义一个变量,类型和REF游标返回类型相同,行类型
BEGIN
  --员工表
  OPEN CUR_EMP FOR
    SELECT * FROM EMP; --打开游标,并关联查询语句
  LOOP
    FETCH CUR_EMP
      INTO V_EMP; --提取游标数据
    EXIT WHEN CUR_EMP%NOTFOUND;
    DBMS_OUTPUT.PUT_LINE(CUR_EMP%ROWCOUNT || ‘  员工编号:‘ || V_EMP.EMPNO ||
                         ‘ 员工姓名:‘ || V_EMP.ENAME);
  END LOOP;
  CLOSE CUR_EMP;
  ------------下面是部门表
  OPEN CUR_EMP FOR
    SELECT * FROM DEPT; --打开游标,并关联查询语句
  LOOP
    FETCH CUR_EMP
      INTO V_DEPT; --提取游标数据
    EXIT WHEN CUR_EMP%NOTFOUND;
    DBMS_OUTPUT.PUT_LINE(CUR_EMP%ROWCOUNT || ‘  部门编号:‘ || V_DEPT.DEPTNO ||
                         ‘ 部门名称:‘ || V_DEPT.DNAME);
  END LOOP;
  CLOSE CUR_EMP;
END;

在Oracle9i之后为了方便用户使用弱类型游标变量,可以使用
SYS_REFCURSOR 来替代  TYPE REF_EMP IS REF CURSOR
上面的声明可以换为:
  CUR_EMP  SYS_REFCURSOR; --定义一个变量类型是上面的REF动态游标也称游标变量
  V_EMP   EMP%ROWTYPE; --定义一个变量,类型和REF游标返回类型相同,行类型
  V_DEPT  DEPT%ROWTYPE; --定义一个变量,类型和REF游标返回类型相同,行类型

--根据用户输入,来输出内容

DECLARE
  --TYPE REFC_T IS REF CURSOR;
  REFC    SYS_REFCURSOR;
  V_ID    NUMBER;
  V_NAME  VARCHAR2(50);
  V_INPUT VARCHAR(1) := UPPER(SUBSTR(‘&input‘, 1, 1));
BEGIN
  IF V_INPUT = ‘E‘ THEN
    OPEN REFC FOR
      SELECT EMPNO, ENAME FROM EMP;
    DBMS_OUTPUT.PUT_LINE(‘=====员工表信息======‘);
  ELSIF V_INPUT = ‘D‘ THEN
    OPEN REFC FOR
      SELECT DEPTNO, DNAME FROM DEPT;
    DBMS_OUTPUT.PUT_LINE(‘=====部门表信息======‘);
  ELSE
    DBMS_OUTPUT.PUT_LINE(‘=====员工表信息(E)或者部门表信息(D)=======‘);
    RETURN;
  END IF;
  FETCH REFC
    INTO V_ID, V_NAME;
  WHILE REFC%FOUND LOOP
    DBMS_OUTPUT.PUT_LINE(REFC%ROWCOUNT || ‘# ‘ || V_ID || ‘  ‘ || V_NAME);
    FETCH REFC
      INTO V_ID, V_NAME;
  END LOOP;
  CLOSE REFC;
END;

时间: 2024-10-13 01:27:36

Oracle cursor的相关文章

Oracle Cursor的使用

When Oracle Database executes a SQL statement, it stores the result set and processing information in an unnamedprivate SQL area. A pointer to this unnamed area, called acursor, lets youretrieve the rows of the result set one at a time.Cursor attribu

oracle cursor 用法总结

PL sql中cursor用法是非常广泛的,常常用于存储过程和函数的返回值,其中用于函数的返回值变相的解决了pl sql 没有表值函数的问题,一般的,在java 调用存储过程,所返回的结果集也是用游标去存储的. 游标分为动态游标和静态游标 1,动态游标定义分两种方式一种是先定义自定义类型如 Type my_cursor is ref cursor .这样就可以定义了一个游标类型,然后我们自己的变量就可以用这个自定义类型去定义了,如 cursorDemo my_cursor (直接用系统自带的sy

oracle cursor(静态)记录

游标定义:游标(Cursor)是处理数据的一种方法,为了查看或者处理结果集中的数据,游标提供了在结果集中一次一行或者多行前进或向后浏览数据的能力.可以把游标当作一个指针,利用游标可以返回它当前指向的行记录(只能返回一行)若要返回多行,则需要不断的滚动,把想要的数据全部查询一遍.游标可以指定结果中的任何位置,然后允许用户对指定位置的数据进行处理.游标的优点:1)允许程序对由查询语句select返回的行集合中的每一行执行相同或不同的操作,而不是对整个行集合执行同一个操作.2)提供对基于游标位置的表中

转 oracle cursor 游标

转自:http://blog.csdn.net/liyong199012/article/details/8948952 游标的概念:     游标是SQL的一个内存工作区,由系统或用户以变量的形式定义.游标的作用就是用于临时存储从数据库中提取的数据块.在某些情况下,需要把数据从存放在磁盘的表中调到计算机内存中进行处理,最后将处理结果显示出来或最终写回数据库.这样数据处理的速度才会提高,否则频繁的磁盘数据交换会降低效率. 游标有两种类型:显式游标和隐式游标.在前述程序中用到的SELECT...I

Oracle Cursor用法总结

cursor分为三种,一是直接声明为cursor变量,二是首先声明类型再声明变量,三是声明为sys_refcursor. (1)直接声明 declare cursor emp_cur  is select *  from emp; emp_record emp%rowtype; begin open emp_cur; loop fetch emp_cur  into emp_record; exit when  emp_cur%notfound; dbms_output.put_line('na

PgSQL · 应用案例 · 阿里云 RDS PostgreSQL 高并发特性 vs 社区版本

摘要: 背景 进程模型数据库,需要为每个会话指派独立的进程与之服务,在连接数非常多,且大都是活跃连接时,进程调度浪费或引入的开销甚至远远大于实际任务需要的开销(例如上下文切换,MEMCPY等),性能下降会较为严重. 背景 进程模型数据库,需要为每个会话指派独立的进程与之服务,在连接数非常多,且大都是活跃连接时,进程调度浪费或引入的开销甚至远远大于实际任务需要的开销(例如上下文切换,MEMCPY等),性能下降会较为严重. PostgreSQL与Oracle Dedicate Server一样,属于

[独孤九剑]Oracle知识点梳理(七)数据库常用对象之Cursor

本系列链接导航: [独孤九剑]Oracle知识点梳理(一)表空间.用户 [独孤九剑]Oracle知识点梳理(二)数据库的连接 [独孤九剑]Oracle知识点梳理(三)导入.导出 [独孤九剑]Oracle知识点梳理(四)SQL语句之DML和DDL [独孤九剑]Oracle知识点梳理(五)数据库常用对象之Table.View [独孤九剑]Oracle知识点梳理(六)数据库常用对象之Procedure.function.Sequence [独孤九剑]Oracle知识点梳理(八)常见Exception

Oracle过程:%TYPE,%ROWTYPE,CURSOR,INTO,FOR...LOOP

/*创建一个过程,ORACLE PL/SQL语法*/ CREATE OR REPLACE PROCEDURE MYPROC AS    v_id     t_user.id%TYPE; /*声明变量,类型与指定表字段一致*/    v_user   t_user%ROWTYPE; /*声明变量,表示一行记录,结构与指定表一行记录一致*/    CURSOR c_user IS SELECT * FROM t_user; /*声明游标,表示多行记录,每一行结构与查询结果一致*/ BEGIN    

Oracle中Cursor的用法

关键字 ?概念 ?类型 ?异常处理 一 概念 游标是SQL的一个内存工作区,由系统或用户以变量的形式定义.游标的作用就是用于临时存储从数据库中提取的数据块.在某些情况下,需要把数据从存放在磁 盘的表中调到计算机内存中进行处理,最后将处理结果显示出来或最终写回数据库.这样数据处理的速度才会提高,否则频繁的磁盘数据交换会降低效率. 二  类型   Cursor类型包含三种: 隐式Cursor,显式Cursor和Ref Cursor(动态Cursor). 1. 隐式Cursor: 1).对于Selec