• Oracle基础 游标


    一、游标  

      游标用来处理从数据库中检索的多行记录(使用SELECT语句)。利用游标,程序可以逐个地处理和遍历一次检索返回的整个记录集。

         为了处理SQL语句,Oracle将在内存中分配一个区域,这就是上下文区。这个区包含了已经处理完的行数、指向被分析语句的指针,整个区是查询语句返回的数据行集。游标就是指向上下文区句柄或指针。

    二、游标的分类:

      1、静态游标:静态游标是在编译时知道其SELECT语句的游标。静态游标又分为两种类型,隐式游标和显示游标。

      2、动态游标:用户为游标使用的查询直到运行的时候才能确定,可以使用REF游标和游标变量满足这个要求。为了使用引用游标,必须声明游标变量。有两种类型的REF游标:强类型REF游标和弱类型REF游标。

    三、显示游标的用法:

      显示游标被用于处理返回多行数据的SELECT 语句,游标名通过CURSOR….IS 语句显示地赋给SELECT 语句。

           (一)使用步骤;

           1)声明游标:CURSOR cursor_name IS select_statement

            2)为查询打开游标:OPEN cursor_name

            3)取得结果放入PL/SQL变量中;

                     FETCH cursor_name INTO list_of_variables;

                   FETCH cursor_name INTO PL/SQL_record;

            4)关闭游标。CLOSE cursor_name

      注意:在声明游标时,select_statement不能包含INTO子句。当使用显示游标时,INTO子句是FETCH语句的一部分。

      例:显示雇员的名称和薪水

    --使用LOOP遍历游标
    DECLARE
      v_name emp.ename%TYPE;
      v_sal emp.sal%TYPE;
      CURSOR cus_emp IS
        SELECT ename,sal FROM emp;                         --声明游标
    BEGIN
       OPEN cus_emp;                                       --打开游标
       LOOP 
          FETCH cus_emp INTO v_name,v_sal;                 --提取游标
          EXIT WHEN cus_emp%NOTFOUND;
          dbms_output.put_line(''||cus_emp%ROWCOUNT||'个用户:  name:'||v_name||'     sal:'||v_sal);
       END LOOP;
       CLOSE cus_emp;                                      --关闭游标
    END;

      显示游标的属性:

      %FOUND:只有在DML语句影响一行或者多行是,则返回TRUE;

      %NOTFOUND:没有影响任何行,则返回TRUE。

      %ROWCOUNT:返回DML语句影响的行数,没有影响则返回0;

      %ISOPEN:返回游标是否打开,在执行SQL之后,Oracle自动关闭SQL游标,所以隐式游标的%isopen属性始终未false;

      另一种方式:

    --使用for来简化游标遍历
    DECLARE
      CURSOR cus_emp IS
        SELECT ename,sal FROM emp;
    BEGIN
       FOR record_emp IN cus_emp
       LOOP 
          dbms_output.put_line(''||cus_emp%ROWCOUNT||'个用户:  name:'||record_emp.ename||'     sal:'||record_emp.sal);
       END LOOP;
    END;

      record_emp是plsql声明的的记录变量,此变量的属性为声明为%ROWTYPE类型,作用域在FOR循环之内,即在FOR循环外就不能访问了。


      循环游标的特性:
      (1)从游标中提取了所有记录之后自动终止。
      (2)提取和处理游标中的每一条记录。
      (3)如果在提取记录之后%NOTFOUND属性返回TRUE,则终止循环。如果未返回任何行,则不进入循环。

    游标案例:  

    --给员工加薪,按员工入职时间进行加薪,每年加100,1000封顶
    DECLARE
      v_date emp.hiredate%TYPE;
      v_empno emp.empno%TYPE;
      v_money NUMBER;
      CURSOR cur_emp IS
        SELECT empno,hiredate FROM emp;
    BEGIN
      OPEN  cur_emp;
      LOOP
         FETCH cur_emp INTO v_empno,v_date;
         EXIT WHEN cur_emp%NOTFOUND;
         v_money := 100*(1990-to_char(v_date,'yyyy'));
         IF v_money<1000 THEN
            UPDATE emp SET sal=sal+v_money WHERE empno=v_empno;
         ELSE
            UPDATE emp SET sal=sal+1000 WHERE empno=v_empno;
         END IF;   
      END LOOP;
    END;

     带参数的游标

      语法:

      CURSOR cursor_name[(parameter[,parameter],...)] IS select_statement;

      定义参数的语法如下:Parameter_name [IN] data_type[{:=|DEFAULT} value]  

      例:接收用户输入的部门编号,用for循环和游标,打印出此部门的所有雇员的所有信息(使用循环游标)
    DECLARE
      CURSOR C_DEPT(P_DEPTNO NUMBER) IS
        SELECT * FROM EMP WHERE EMP.DEPTNO = P_DEPTNO;
      R_EMP EMP%ROWTYPE;
    BEGIN
      FOR R_EMP IN C_DEPT(30) LOOP
        DBMS_OUTPUT.PUT_LINE('员工号:' || R_EMP.EMPNO || '员工名:' || R_EMP.ENAME ||
                             '工资:' || R_EMP.SAL);
      END LOOP;
    END;
    
    

    四、隐式游标:

      所有的隐式游标都被假设为只返回一条记录。
      使用隐式游标时,用户无需进行声明、打开及关闭。PL/SQL隐含地打开、处理,然后关掉游标。多条sql语句 隐式游标SQL永远指的是最后一条sql语句的结果,主要使用在update 和 delete语句上。

      隐式游标的四个属性:

    属性 说明
     SQL%rowcount  影响的记录的行数整数(用来判断插入,更新修改是否成功,必须在comit之前,否则提交后结果为0.)
     SQL%found  影响到了记录 true()
     SQL%notfound  没有影响到记录 true
     SQL%isopen  是否打开 布尔值 永远是false


    例如:

    DECLARE
      row_emp emp%ROWTYPE;
    BEGIN
      SELECT ename,sal INTO row_emp.ename,row_emp.sal
      FROM emp WHERE emp.empno = 7369;
      --判断是否查到数据
      if(SQL%ROWCOUNT=1) THEN
        dbms_output.put_line('找到了');
      END IF;
      --另一种方式判断
      IF(SQL%Found) THEN
        dbms_output.put_line('找到了');
      END IF;
    
      dbms_output.put_line('ename:'||row_emp.ename||'    sal:'||row_emp.sal);
    END;

    上述游标自动打开,并把相关值赋给对应变量,然后关闭。执行完后,PL/SQL变量rowemp.ename,rowemp.sal中已经有了值。


    五:动态游标

      静态游标是在声明就已经确定查询语句,如果用户需要在运行时动态决定游标执行的查询,就需要使用动态游标(REF游标)。

      动态游标分为两类:强类型游标弱类型游标

      动态游标使用步骤:

      1、声明动态游标类型;

      2、打开游标,指定游标查询;

      3、提取游标。

      4、关闭游标。

      例:

      强类型游标,使用return声明的游标为强类型游标。在对游标进行绑定查询只能绑定游标返回的类型rowtype。

    --强类型的动态游标,查询emp表中的数据
    DECLARE
      TYPE ref_cur IS REF CURSOR    --声明游标类型
      RETURN emp%ROWTYPE;       --带返回值的为强类型动态游标
      refcur_emp ref_cur;         --游标类型对象
      v_emp emp%ROWTYPE;
    BEGIN
      OPEN refcur_emp FOR        --将游标绑定到一个查询语句,因为声明的是强类型,所以只能绑定emp;
        SELECT * FROM emp;    
      LOOP
        FETCH refcur_emp INTO v_emp;     --提取游标内容
        EXIT WHEN refcur_emp%NOTFOUND;
        dbms_output.put_line(refcur_emp%Rowcount||'、name:'||v_emp.ename||'    sal:'||v_emp.sal);
      END LOOP;
      CLOSE refcur_emp;
    END;

      

      弱类型游标:可以用来绑定多个查询结果。

      例:

    --弱类型游标
    DECLARE
      TYPE refcur IS REF CURSOR;   --未定义返回类型为弱类型游标
      rc refcur;
      v_name emp.ename%TYPE;
      v_deptname dept.dname%TYPE;
    BEGIN
      OPEN rc FOR SELECT ename,dname FROM emp e,dept d WHERE e.deptno = d.deptno;  --绑定查询
      LOOP
        FETCH rc INTO v_name,v_deptname;    
        EXIT WHEN rc%NOTFOUND;
        dbms_output.put_line('name:'||v_name||'               deptname:'||v_deptname);
      END LOOP;
      CLOSE rc;
    END;

      例:

    --根据输入的内容绑定游标
    DECLARE 
      TYPE refcur IS REF CURSOR;
      rc refcur;
      v_tablename VARCHAR2(10) := '&tab';
      v_id NUMBER;
      v_name VARCHAR2(20);
    BEGIN
      IF(v_tablename = 'e') THEN
        OPEN rc FOR 
          SELECT e.empno,e.ename INTO v_id,v_name FROM emp e;
          dbms_output.put_line('=========员工信息=============');
      Elsif(v_tablename = 'd') THEN
        OPEN rc FOR 
          SELECT d.deptno,d.dname INTO v_id,v_name FROM dept d;
          dbms_output.put_line('=========部门信息=============');
      ELSE
          dbms_output.put_line('输入错误,请输入e或者d!');
          RETURN;
      END IF;  
      
      LOOP 
        FETCH rc INTO v_id,v_name;
        dbms_output.put_line('#'||rc%Rowcount||'   id:'||v_id||'   name:'||v_name);
        EXIT WHEN rc%NOTFOUND;
      END LOOP;
    END;

    六、动态游标和静态游标的区别:  

      1、静态游标是静态定义,REF 游标是动态关联;

      2、使用REF 游标需REF 游标变量。

      3、REF 游标能做为参数进行传递,而静态游标是不可能的。

  • 相关阅读:
    visual studio 2013 中配置OpenCV2.4.13 姿势
    全栈技能图谱
    Lua 基础
    Lua手动编译姿势
    字符串专题:几种奇怪的算法
    字符串专题:KMP POJ 3561
    字符串专题:后缀数组
    字符串专题:map POJ 1002
    2015安徽省赛 G.你来擒孟获
    求方程解问题
  • 原文地址:https://www.cnblogs.com/zhengcheng/p/4206046.html
Copyright © 2020-2023  润新知