zoukankan      html  css  js  c++  java
  • PL/SQLCursor

    显式游标
    隐式游标
    游标变量
    游标子查询

    游标的概念:

     游标给出了数据的一个子集,这个子集是由某个查询语句定义的,在打开游标的时候,将数据加载到内存中,在游标未关闭的过程中,该数据将一直存在在内存中,游标指向PGA(PROCESS GLOBAL AREA)的一个内存区域,一般将PGA称为上下文区域。该区域存储下列数据:

      1、查询语句返回的记录行。

      2、查询语句处理的记录行数目。

      3、指向共享池中(Share Pool)中已解析查询语句的一个指针。

    如果游标打开后,又新增或者删除了数据,则新增添和删除的数据就不会反馈到游标的查询结果中,打开游标就像是获取当前数据的一个快照:例如

     1 DECLARE
    2 V_ROWID ROWID;
    3 CURSOR DEPT_CURSOR_1 IS
    4 SELECT ROWID FROM TEST_DEPT T WHERE T.DEPTNO < 100;
    5 CURSOR DEPT_CURSOR_2 IS
    6 SELECT ROWID FROM TEST_DEPT T WHERE T.DEPTNO < 100;
    7 BEGIN
    8 --打开游标1,将其中的数据删除
    9 OPEN DEPT_CURSOR_1;
    10 DELETE FROM TEST_DEPT T WHERE T.DEPTNO < 100;
    11 --打开游标2
    12 OPEN DEPT_CURSOR_2;
    13
    14 --检查游标1
    15 FETCH DEPT_CURSOR_1
    16 INTO V_ROWID;
    17 IF DEPT_CURSOR_1%ROWCOUNT > 0 THEN
    18 DBMS_OUTPUT.PUT_LINE('游标1包含删除的数据');
    19 ELSE
    20 DBMS_OUTPUT.PUT_LINE('游标1不包含删除的数据');
    21 END IF;
    22 --检查游标1
    23 FETCH DEPT_CURSOR_2
    24 INTO V_ROWID;
    25 IF DEPT_CURSOR_2%ROWCOUNT > 0 THEN
    26 DBMS_OUTPUT.PUT_LINE('游标2包含删除的数据');
    27 ELSE
    28 DBMS_OUTPUT.PUT_LINE('游标2不包含删除的数据');
    29 END IF;
    30 CLOSE DEPT_CURSOR_1;--关闭游标
    31 CLOSE DEPT_CURSOR_2;
    32 ROLLBACK;--回滚
    33 EXCEPTION WHEN OTHERS THEN
    34 DBMS_OUTPUT.PUT_LINE(Sqlerrm);
    35 END;

    结果:

    --显式游标的四个属性
    /*%ROWCOUNT
    %FOUND
    %NOTFOUND
    %ISOPEN*/

     1 --定义一个游标
    2 DECLARE
    3 CURSOR EMP_CURSOR_1 IS(
    4 SELECT * FROM EMP);
    5 CURSOR EMP_CURSOR_2 IS(
    6 SELECT * FROM EMP);
    7 V_EMP_RECORD EMP%ROWTYPE;
    8 BEGIN
    9 --打开游标1
    10 IF NOT EMP_CURSOR_1%ISOPEN THEN
    11 OPEN EMP_CURSOR_1;
    12 DBMS_OUTPUT.PUT_LINE('OPEN CURSOR1');
    13 END IF;
    14 --提取数据--使用基本LOOP循环
    15 LOOP
    16 FETCH EMP_CURSOR_1
    17 INTO V_EMP_RECORD;
    18 DBMS_OUTPUT.PUT_LINE('ENAME:' || V_EMP_RECORD.ENAME);
    19 EXIT WHEN EMP_CURSOR_1%NOTFOUND;
    20 END LOOP;
    21 CLOSE EMP_CURSOR_1;
    22 OPEN EMP_CURSOR_1;
    23 --提取数据--使用WHILE-----LOOP循环
    24 WHILE EMP_CURSOR_1%FOUND LOOP
    25 FETCH EMP_CURSOR_1
    26 INTO V_EMP_RECORD;
    27 DBMS_OUTPUT.PUT_LINE('ENAME:' || V_EMP_RECORD.ENAME);
    28 END LOOP;
    29 --关闭游标
    30 IF EMP_CURSOR_1%ISOPEN THEN
    31 CLOSE EMP_CURSOR_1;
    32 DBMS_OUTPUT.PUT_LINE('CLOSE CURSOR');
    33 END IF;
    34 DBMS_OUTPUT.PUT_LINE('=============分隔符==============');
    35 --提取数据--使用FOR-----LOOP循环.使用这种循环,会自动的打开和关闭游标
    36 FOR IDX IN EMP_CURSOR_2 LOOP
    37 DBMS_OUTPUT.PUT_LINE('ENAME:' || IDX.ENAME);
    38 END LOOP;
    39 --测试%ROWCOUNT属性
    40 OPEN EMP_CURSOR_1;
    41 FETCH EMP_CURSOR_1
    42 INTO V_EMP_RECORD;
    43 DBMS_OUTPUT.PUT_LINE('ROWCOUNT' || EMP_CURSOR_1%ROWCOUNT);
    44 CLOSE EMP_CURSOR_1;
    45 DBMS_OUTPUT.PUT_LINE(CHR(1));
    46 END;

    --隐式游标的四个属性

    SQL%ROWCOUNT
    SQL%FOUND
    SQL%NOTFOUND
    SQL%ISOPEN--永远为FALSE

    1 DECLARE
    2 V_DEPTNO DEPT.DEPTNO%TYPE := &部门编号;
    3 BEGIN
    4 UPDATE TEST_DEPT T SET T.LOC = '西安市' WHERE T.DEPTNO = V_DEPTNO;
    5 IF SQL%NOTFOUND THEN
    6 DBMS_OUTPUT.PUT_LINE('没有该部门');
    7 END IF;
    8 END;


    在进行更新操作的过程中,最好使用for update,可以添加nowait,当该行数据被其他锁定时,会提示:

    1  DECLARE
    2 CURSOR EMP_TEST_CUR IS
    3 SELECT * FROM EMP_TEST FOR UPDATE OF ENAME NOWAIT;
    4 BEGIN
    5 FOR EMP_REC IN EMP_TEST_CUR LOOP
    6 UPDATE EMP_TEST SET ename = '小明' WHERE CURRENT OF EMP_TEST_CUR;
    7 END LOOP;
    8 END;

    --游标变量的使用

     1 --游标变量的使用
    2 DECLARE
    3 TYPE EMP_CURSOR IS REF CURSOR RETURN EMP%ROWTYPE;
    4 V_EMP_CURSOR EMP_CURSOR;
    5 V_EMP_RECORD EMP%ROWTYPE;
    6 BEGIN
    7 --打开游标,使用FOR来赋初始值
    8 OPEN V_EMP_CURSOR FOR
    9 SELECT * FROM EMP;
    10 --提取数据
    11 FETCH V_EMP_CURSOR
    12 INTO V_EMP_RECORD;
    13 --输出数据
    14 DBMS_OUTPUT.PUT_LINE('DEPTNO:' || V_EMP_RECORD.DEPTNO ||
    15 'ENAME:' || V_EMP_RECORD.ENAME);
    16 CLOSE V_EMP_CURSOR;
    17 END;

    --游标子查询

     1 --游标子查询
    2 DECLARE
    3 EMP_CURSOR SYS_REFCURSOR;
    4 EMP_RECORD EMP%ROWTYPE;
    5 DEPT_NAME DEPT.DNAME%TYPE;
    6 CURSOR DEPT_CURSOR IS
    7 SELECT D.DNAME, CURSOR (SELECT * FROM EMP E WHERE E.DEPTNO = D.DEPTNO)
    8 FROM DEPT D;
    9 BEGIN
    10 OPEN DEPT_CURSOR;
    11 LOOP
    12 FETCH DEPT_CURSOR
    13 INTO DEPT_NAME, EMP_CURSOR;
    14 EXIT WHEN DEPT_CURSOR%NOTFOUND;
    15 DBMS_OUTPUT.PUT_LINE('DNAME:' || DEPT_NAME);
    16 LOOP
    17 FETCH EMP_CURSOR
    18 INTO EMP_RECORD;
    19 EXIT WHEN EMP_CURSOR%NOTFOUND;
    20 DBMS_OUTPUT.PUT_LINE('ENAME:' || EMP_RECORD.ENAME);
    21 END LOOP;
    22 END LOOP;
    23 END;

    REF_CURSOR的使用:

     1 DECLARE
    2 TYPE EMP_CURSOR_REF IS REF CURSOR;
    3 EMP_CURSOR EMP_CURSOR_REF;
    4 EMP_RECORD EMP%ROWTYPE;
    5 BEGIN
    6 OPEN EMP_CURSOR FOR
    7 SELECT * FROM EMP;
    8 FETCH EMP_CURSOR
    9 INTO EMP_RECORD;
    10 WHILE EMP_CURSOR%FOUND LOOP
    11 DBMS_OUTPUT.PUT_LINE('ename:' || EMP_RECORD.ENAME);
    12 FETCH EMP_CURSOR
    13 INTO EMP_RECORD;
    14 END LOOP;
    15 END;

    游标和varray的联合使用

     1 DECLARE
    2 TYPE EMP_VARRAY IS VARRAY(100) OF EMP%ROWTYPE;
    3 EMPS EMP_VARRAY;
    4 CURSOR EMP_CURSOR IS
    5 SELECT * FROM EMP;
    6 COUNTS PLS_INTEGER := 0;
    7 BEGIN
    8 --初始化数组(下标从1开始)
    9 EMPS := EMP_VARRAY();
    10 FOR IDX IN EMP_CURSOR LOOP
    11 --添加一行新数据
    12 COUNTS := COUNTS + 1;
    13 EMPS.EXTEND();
    14 EMPS(COUNTS).EMPNO := IDX.EMPNO;
    15 EMPS(COUNTS).ENAME := IDX.ENAME;
    16 EMPS(COUNTS).JOB := IDX.JOB;
    17 EMPS(COUNTS).MGR := IDX.MGR;
    18 EMPS(COUNTS).HIREDATE := IDX.HIREDATE;
    19 EMPS(COUNTS).SAL := IDX.SAL;
    20 EMPS(COUNTS).COMM := IDX.COMM;
    21 EMPS(COUNTS).DEPTNO := IDX.DEPTNO;
    22 END LOOP;
    23
    24 FOR IDX1 IN 1 .. EMPS.COUNT LOOP
    25 DBMS_OUTPUT.PUT_LINE('empno:' || EMPS(IDX1).EMPNO);
    26 END LOOP;
    27 END;






    I believe that we are who we choose to be. Nobody‘s going to come and save you, you‘ve got to save yourself. 我相信我们成为怎样的人是我们自己的选择。没有人会来拯救你,你必须要自己拯救自己。
  • 相关阅读:
    8-21模拟赛解题报告
    8-20模拟赛解题报告
    8-19模拟赛解题报告
    8-18模拟赛解题报告
    8-27复习(写题)报告
    [省赛训练(DP)]Course Selection System
    Trie(字典树)的基本操作与应用(一般与字符串前缀相关)
    [算法学习]欧拉筛
    构造函数运行的机制
    js基本数据类型之间的转换
  • 原文地址:https://www.cnblogs.com/caroline/p/2284292.html
Copyright © 2011-2022 走看看