游标

作者: _拾年丶 | 来源:发表于2018-09-01 14:13 被阅读0次
    游标:用来提取多行数据

    Oracle 打开一个工作区(内存区域)来保存多行查询的结果集,
    游标就是给这个工作区命的名称,并能用于处理由多行查询而返回的记录行。

    隐式游标: 默认的 DML 语句和 select 语句都有隐式游标。
    显示游标: 开发中给工作区命名,并且可以进行操作。

    %ISOPEN Boolean 游标打开,则返回True(游标打开之后,不能再次打开,游标关闭之后,不能再次关闭)
    %NOTFOUND Boolean 如果最近抓取没有获得记录,返回True
    %FOUND Boolean 如果最近抓取获得记录,返回True
    %ROWCOUNT Number 返回到目前为止获取的记录数


    使用游标的步骤:

    1. 定义游标 CURSOR c_tb_stuu IS SELECT * FROM tb_stuu;
    2. 打开游标 OPEN c_tb_stuu;
    3. fetch游标 FETCH c_tb_stuu INTO r_tb_stuu;
      游标有个指针,默认指向第一行之上,fetch将指针向下移动,指向第N行数据,
      如果有数据,NOTFOUND返回false,FOUND返回true。
      如果到末尾,会一直抓取最后一条数据
    4. 关闭游标 CLOSE c_tb_stuu;

    第一个例子: 使用游标提取 tb_stuu 的所有数据

    DECLARE 
       -- 1. 定义游标(将SELECT * FROM tb_stuu 数据的查询结果放入 c_stuu 中)
       CURSOR c_stuu IS SELECT * FROM tb_stuu;
       -- 2. 定义rowtype(把抓取到的数据放入 r_stuu 中)
       r_stuu tb_stuu%ROWTYPE;
    BEGIN
      OPEN c_stuu;
           -- 提取数据
           LOOP
               --fetch 提取到数据放入变量r_stuu中
             FETCH c_stuu INTO r_stuu;
             EXIT WHEN c_stuu%NOTFOUND;
             dbms_output.put_line(r_stuu.id || ' '||r_stuu.name);
           END LOOP;
      CLOSE c_stuu;
    END;
    
    SELECT * FROM tb_stuu;
    SELECT * FROM tb_student;
    

    带参数的游标
    第二个例子:使用游标提取 tb_stuu 的所有数据,同时提取每个班级的学生数据
    注意:传递是形参,形参是不用长度的

    DECLARE
        -- 此处 stuu 表,主要充当班级表 
        -- 创建了一个游标,保存 tb_stuu 表中的所有数据
        CURSOR c_stuu IS SELECT * FROM tb_stuu;
        
        r_stuu tb_stuu%ROWTYPE;
        
        -- 此处 student 表,充当学生表
        -- 创建了一个游标,保存 tb_student 表中的所有数据
        -- 并且接收了一个参数,这个参数主要是来自 tb_stuu 表中的 id 值
        -- 用了之后,效果是把两张表绑定到一起
        CURSOR c_student(v_id tb_stuu.id%TYPE) IS 
        SELECT * FROM tb_student WHERE id = v_id;
        
        r_student tb_student%ROWTYPE;
    BEGIN
      -- 外层打开 stuu 游标,也就是先使用 stuu(班级表)中的数据
      -- 会先循环一遍,一共会循环 4 次,把对应的数据抓取出来
      -- 1
      OPEN c_stuu;
           LOOP
             FETCH c_stuu INTO r_stuu;
             -- 直到 c_stuu 中的值找不到的时候,就退出了
             EXIT WHEN c_stuu%NOTFOUND;
             dbms_output.put_line('班级:' || r_stuu.id||' '||r_stuu.name);
             
             -- 内层打开 student 游标,接着需要使用 student(学生表)中的数据
             -- 也会循环,注意,外面循环一次,里面循环 5 次。
             -- 查找当前班级的学生信息 
             OPEN c_student(r_stuu.id);
                  LOOP
                   -- 抓取数据
                    FETCH c_student INTO r_student;
                    -- 直到 c_student 中的值找不到的时候,就退出了
                    EXIT WHEN c_student%NOTFOUND;
                    dbms_output.put_line(r_student.id||' '||r_student.name);
                  END LOOP;
             CLOSE c_student;
             
           END LOOP;
      CLOSE c_stuu;
    END;
    

    练习:
    使用游标提取 scott 用户的 dept 的所有数据,
    同时提取每个部门的员工数据,打印在控制台

    SELECT * FROM scott.dept;
    SELECT * FROM scott.emp;
    
    DECLARE
       CURSOR c_dept IS SELECT * FROM scott.dept;
       CURSOR c_emp(v_deptno scott.dept.deptno%TYPE) 
       IS SELECT * FROM scott.emp WHERE deptno = v_deptno;
    BEGIN
     -- 先处理部门,因为一个部门中,可以有多个员工
      FOR r_dept IN c_dept
        LOOP
          dbms_output.put_line('部门:' || r_dept.deptno||' '||r_dept.dname);
          
          FOR r_emp IN c_emp(r_dept.deptno)
            LOOP
              dbms_output.put_line(r_emp.empno||' '||r_emp.ename||'  '||r_emp.job||'  '||r_emp.sal);
            END LOOP;
          
          dbms_output.put_line('***************************************');
          
        END LOOP;
    END;
    
    

    相关文章

      网友评论

          本文标题:游标

          本文链接:https://www.haomeiwen.com/subject/ltaywftx.html