• Oracle中游标的用法


    什么是游标?

    ①从表中检索出结果集,从中每次指向一条记录进行交互的机制。

    ②关系数据库中的操作是在完整的行集合上执行的。

    由 SELECT 语句返回的行集合包括满足该语句的 WHERE 子句所列条件的所有行。由该语句返回完整的行集合叫做结果集。

    应用程序,尤其是互动和在线应用程序,把完整的结果集作为一个单元处理并不总是有效的。

    这些应用程序需要一种机制来一次处理一行或连续的几行。而游标是对提供这一机制的结果集的扩展。

    游标是通过游标库来实现的。游标库是常常作为数据库系统或数据访问 API 的一部分而得以实现的软件,用来管理从数据源返回的数据的属性(结果集)。这些属性包括并发管理、在结果集中的位置、返回的行数,以及是否能够在结果集中向前和/或向后移动(可滚动性)。

    游标跟踪结果集中的位置,并允许对结果集逐行执行多个操作,在这个过程中可能返回至原始表,也可能不返回至原始表。

    换句话说,游标从概念上讲基于数据库的表返回结果集。

    由于它指示结果集中的当前位置 ,就像计算机屏幕上的光标指示当前位置一样,“游标”由此得名。

    游标有什么作用?

    ①指定结果集中特定行的位置。

    ②基于当前的结果集位置检索一行或连续的几行。

    ③在结果集的当前位置修改行中的数据。

    ④对其他用户所做的数据更改定义不同的敏感性级别。

    ⑤可以以编程的方式访问数据库。

    一、游标:

    1、概念:

    游标的本质是一个结果集resultset,主要用来临时存储从数据库中提取出来的数据块。

    二、游标的分类:

    1、显式游标:

    由用户定义,需要的操作:定义游标、打开游标、提取数据、关闭游标,主要用于对查询语句的处理。

    属性:%FOUND %NOTFOUND %ISOPEN %ROWCOUNT

    Example:打印emp表的员工信息

    DECLARE
     CURSOR emp_cursor IS SELECT empno,ename,job FROM emp;
     v_empno emp.empno%TYPE;
     v_name emp.ename%TYPE;
     v_job emp.job%TYPE;
    BEGIN
     OPEN emp_cursor;
     LOOP
     FETCH emp_cursor INTO v_empno,v_name,v_job;
     DBMS_OUTPUT.PUT_LINE('员工号为:'||v_empno||'姓名是'||v_name||'职位:'||v_job);
     EXIT WHEN emp_cursor%NOTFOUND;
     END LOOP;
     CLOSE emp_cursor;
    END;

    这里严格按照显示游标的书写规则:DECLARE emp_cursor定义游标OPEN emp_cursor打开游标FETCH emp_cursor INTO...提取数据CLOSE emp_cursor关闭游标,因为提取出来的数据属于多行,所以通过loop循环打印即可。

    Example2:检验游标是否打开,如果打开显示提取行数

    DECLARE
     CURSOR emp_cursor IS SELECT empno,ename,job FROM emp;
     v_empno emp.empno%TYPE;
     v_name emp.ename%TYPE;
     v_job emp.job%TYPE;
    BEGIN
     OPEN emp_cursor;
     LOOP
      FETCH emp_cursor INTO v_empno,v_name,v_job;
      EXIT WHEN emp_cursor%NOTFOUND;
     END LOOP;
     IF emp_cursor%ISOPEN THEN
     DBMS_OUTPUT.PUT_LINE('游标已打开');
     DBMS_OUTPUT.PUT_LINE('读取了'||emp_cursor%ROWCOUNT||'行');
     ELSE
     DBMS_OUTPUT.PUT_LINE('游标没有打开');
     END IF;
     CLOSE emp_cursor;
    END;

    -- 游标(光标cursor)
    --在写Java程序中有集合的概念, 那么在pl/sql中也会用到多条记录, 这时候我们就要用到游标, 游标可以存储查询返回的多条数据。
    -- 语法:cursor 游标名(参数 数据类型,参数 数据类型) is select 语句;
    -- 列如 cursor c1 is select ename from emp;
    -- 游标使用步骤
    -- 打开游标:open c1
    -- 取一行游标值 fetch c1 into pjob;(取一行数据到变量中)
    -- 关闭游标 close c1
    -- 游标结束方式 exit when c1%notfound

    -- 查询姓名和工资
    declare
    cursor vrows is select * from emp;
    vrow emp%Rowtype;
    begin
    open vrows;
    loop
    fetch vrows into vrow;
    exit when vrows%notfound;
    dbms_output.put_line('姓名:'||vrow.ename||' '||'工资:'||vrow.sal);
    end loop;
    close vrows;
    end;

    -- 指定部门下的员工工资
    declare
    cursor deptSal(dno number) is select * from emp where deptno=dno;
    dep emp%rowtype;
    begin
    open deptSal(10);
    loop
    fetch deptSal into dep;
    exit when deptSal%notfound;
    dbms_output.put_line('员工姓名:'||dep.ename||' '||'工资:'||dep.sal);
    end loop;
    close deptSal;
    end;
    -- 引用系统游标
    declare
    vrows sys_refcursor; -- 引用系统游标
    vrow emp%rowtype; -- 记录一行数据
    begin
    open vrows for select * from emp;
    loop
    fetch vrows into vrow;
    exit when vrows%notfound;
    dbms_output.put_line('姓名:'||vrow.ename||' '||'工资:'||vrow.sal);
    end loop;
    close vrows;
    end;

    -- 使用for循环遍历游标
    declare
    -- 申明游标
    cursor vrows is select * from emp;
    begin
    for vrow in vrows loop
    dbms_output.put_line('姓名为:'||vrow.ename||'工资为:'||vrow.sal);
    end loop;
    end;

    -- 按员工的工种长工资,总裁1000元,经理长800元其, 他人员长400元
    declare
    cursor vrows is select * from emp;
    vrow emp%rowtype;
    begin
    open vrows;
    loop
    fetch vrows into vrow;
    exit when vrows%notfound;
    if vrow.job='PRESIDENT' then
    update emp set sal=sal+1000 where empno=vrow.empno;
    elsif vrow.job='MANAGER' then
    update emp set sal=sal+800 where empno=vrow.empno;
    else
    update emp set sal=sal+400 where empno=vrow.empno;
    end if;
    dbms_output.put_line('姓名为:'||vrow.ename||'工资为:'||vrow.sal);
    end loop;
    close vrows;
    end;

    2、隐式游标:由系统定义并为它创建工作区域,并且隐式的定义打开提取关闭,隐式游标的游标名就是'SQL',属性和显示游标相同,主要用于对单行select语句或dml操作进行处理。Example:又用户输入员工号修改员工工资如成功则打印输出成功标志。

    3、参数游标:

    在定义游标时加入参数的游标,可以配合游标for循环快速找到需要的数据。这里先讲一下游标for循环

    A、游标FOR循环:

    隐含的执行了打开提取关闭数据,代码精简很多。Expression:

    FOR table_record IN table_cursor LOOP

      STATEMENT;

    END LOOP;

    三、使用游标修改数据的注意事项

    1、使用游标修改数据时,为防止他人在自己操作数据时对数据进行修改,oracle提供for update子句进行加锁。

    同时在你使用update或delete时,必须使用where current of+name_cursor语句,以及在最后记得提交。如果是级联操作则可以使用for update of 来进行相关表的加锁。

    -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    声明游标;CURSOR cursor_name IS select_statement

    --For 循环游标
    --(1)定义游标
    --(2)定义游标变量
    --(3)使用for循环来使用这个游标
    declare
    --类型定义
    cursor c_job
    is
    select empno,ename,job,sal
    from emp
    where job='MANAGER';
    --定义一个游标变量v_cinfo c_emp%ROWTYPE ,该类型为游标c_emp中的一行数据类型
    c_row c_job%rowtype;
    begin
    for c_row in c_job loop
    dbms_output.put_line(c_row.empno||'-'||c_row.ename||'-'||c_row.job||'-'||c_row.sal);
    end loop;
    end;



    --Fetch游标
    --使用的时候必须要明确的打开和关闭

    declare
    --类型定义
    cursor c_job
    is
    select empno,ename,job,sal
    from emp
    where job='MANAGER';
    --定义一个游标变量
    c_row c_job%rowtype;
    begin
    open c_job;
    loop
    --提取一行数据到c_row
    fetch c_job into c_row;
    --判读是否提取到值,没取到值就退出
    --取到值c_job%notfound 是false
    --取不到值c_job%notfound 是true
    exit when c_job%notfound;
    dbms_output.put_line(c_row.empno||'-'||c_row.ename||'-'||c_row.job||'-'||c_row.sal);
    end loop;
    --关闭游标
    close c_job;
    end;

    --1:任意执行一个update操作,用隐式游标sql的属性%found,%notfound,%rowcount,%isopen观察update语句的执行情况。
    begin
    update emp set ENAME='ALEARK' WHERE EMPNO=7469;
    if sql%isopen then
    dbms_output.put_line('Openging');
    else
    dbms_output.put_line('closing');
    end if;
    if sql%found then
    dbms_output.put_line('游标指向了有效行');--判断游标是否指向有效行
    else
    dbms_output.put_line('Sorry');
    end if;
    if sql%notfound then
    dbms_output.put_line('Also Sorry');
    else
    dbms_output.put_line('Haha');
    end if;
    dbms_output.put_line(sql%rowcount);
    exception
    when no_data_found then
    dbms_output.put_line('Sorry No data');
    when too_many_rows then
    dbms_output.put_line('Too Many rows');
    end;
    declare
    empNumber emp.EMPNO%TYPE;
    empName emp.ENAME%TYPE;
    begin
    if sql%isopen then
    dbms_output.put_line('Cursor is opinging');
    else
    dbms_output.put_line('Cursor is Close');
    end if;
    if sql%notfound then
    dbms_output.put_line('No Value');
    else
    dbms_output.put_line(empNumber);
    end if; dbms_output.put_line(sql%rowcount);
  • 相关阅读:
    mongoDB看这篇就够了
    放不下
    jmeter连接不上MySQL数据库的原因以及解决方法
    SecureCRT自动断开连接的解决方法
    Linux及Windows查看占用端口的进程
    网络基础知识
    selenium中driver.close()和driver.quit()的不同点
    day2_窗口句柄切换
    day6_异常捕捉
    day6_logging模块
  • 原文地址:https://www.cnblogs.com/mxh168/p/13965760.html
Copyright © 2020-2023  润新知