美文网首页程序园
Oracle SQL 学习笔记20 - Cursor 2

Oracle SQL 学习笔记20 - Cursor 2

作者: 赵阳_c149 | 来源:发表于2020-02-08 10:25 被阅读0次

    Implicit 和 Explicit Cursors

    Cursors

    任何sql执行都对应一个Cursor:

    • Implicit Cursor
      由PL/SQL声明和管理,用于所有的DML和PL/SQL SELECT语句。
    • Explicit Cursor
      由程序员声明和管理

    Explicit Cursor 操作

    Ex_Cursor.JPG

    Explicit Cursor 控制流

    Cursor_control.JPG
    Cursor_control_2.JPG

    定义、控制和使用 Explicit cursors

    定义Cursor

    • 语法
    CURSOR  cursor_name IS
      select_statement;
    
    • 实例
    DELCARE
      CURSOR  emp_cursor  IS
        SELECT  employee_id,  last_name  FROM employees
        WHERE  department_id  =  30;
    
    DECLARE
      locid  NUMBER  :=  1700;
      CURSOR  dept_cursor  IS
        SELECT  *  FROM  departments
        WHERE  location_id  =  locid;
    

    打开 Cursor

    DECLARE
      CURSOR  emp_cursor  IS
        SELECT  employee_id,  last_name  FROM  employees
        WHERE  department_id  =  30;
    ..
    BEGIN
      OPEN  emp_cursor;
    

    从 Cursor 提取数据:例1

    SET  SERVEROUTPUT  ON
    DECLARE
      CURSOR  emp_cursor  IS
        SELECT  employee_id,  last_name  FROM  employees
        WHERE  department_id  =  30;
      empno  employees.employee_id%TYPE;
      lname  employees.last_name%TYPE;
    BEGIN
      if  NOT  emp_cursor%ISOPEN  then
        OPEN  emp_cursor;
      end  if;
      FETCH  emp_cursor  INTO  empno,  lname;
      DBMS_OUTPUT.PUT_LINE(  empno  ||' '||lname);
      ...
    END;
    /
    

    从 Cursor 提取数据:例2

    SET  SERVEROUTPUT  ON
    DECLARE
      CURSOR  emp_cursor  IS
        SELECT  employee_id,  last_name  FROM  employees
        WHERE  department_id  =  30;
      empno  employees.employee_id%TYPE;
      lname  employees.last_name%TYPE;
    BEGIN
      if  NOT  emp_cursor%ISOPEN  then
        OPEN  emp_cursor;
      end  if;
      LOOP
        FETCH  emp_cursor  INTO  empno,  lname;
        EXIT  WHEN  emp_cursor%NOTFOUND;
        DBMS_OUTPUT.PUT_LINE(  empno  ||' '||lname);
      END  LOOP;
      ...
    END;
    /
    

    Cursors 和 Records

    直接将 cursor 当前活跃数据行 fetch 进入 record 变量。

    DECLARE
      CURSOR  emp_cursor  IS
        SELECT  employee_id,  last_name  FROM  employees
        WHERE  department_id  =  30;
      emp_record  emp_cursor%ROWTYPE;  
    BEGIN
      OPEN  emp_cursor;
      LOOP  
        FETCH  emp_cursor  INTO  emp_record;
      ...  
    

    Cursor FOR Loops

    • 语法
    FOR  record_name  IN  cursor_name  LOOP
      statement1;
      statement2;
      ...
    END  LOOP;
    

    Cursor FOR Loop 是处理 Explicit Cursor 的快捷方式,它隐式的打开、获取、退出和关闭Cursor。这里,record是隐式声明的。

    • 实例
    SET  SERVEROUTPUT  ON
    DECLARE
      CURSOR  emp_cursor  IS
        SELECT  employee_id,  last_name  FROM  employees
        WHERE  department_id  =  30;
    BEGIN
      FOR  emp_record  IN  emp_cursor  LOOP
          DBMS_OUTPUT.PUT_LINE(  emp_record.employee_id  ||  '  '  ||emp_record.last_name);
      END  LOOP;
    END;
    /
    

    Explicit Cursor 属性

    属性 类型 描述
    %ISOPEN Boolean 如果Cursor已经打开,值为TRUE
    %NOTFOUND Boolean 如果最近的一次FETCH操作没有返回一行数据,值为TRUE
    %FOUND Boolean 如果最近的一次FETCH操作返回一行数据,值为TRUE
    %ROWCOUNT Number 值为目前为止返回的数据行数
    %ISOPEN

    只有在Cursor打开的时候,才能FETCH数据。通常,用%ISOPEN来验证Cursor是否已经打开。

    • 实例
    IF  NOT  emp_cursor%ISOPEN  THEN
      OPEN  emp_cursor;
    END  IF;
    LOOP
      FETCH  emp_cursor...
    
    %ROWCOUNT 和 %NOTFOUND
    SET  SERVEROUTPUT  ON
    DECLARE
      empno  employees.employee_id%TYPE;
      ename  employees.last_name%TYPE;
      CURSOR  emp_cursor  IS
        SELECT  employee_id,  last_name  FROM  employees
    BEGIN
      OPEN  emp_cursor;
      LOOP
        FETCH  emp_cursor  INTO  empno,  ename;
        EXIT  WHEN  emp_cursor%ROWCOUNT  >  10  OR  emp_cursor%NOTFOUND  
        DBMS_OUTPUT.PUT_LINE(TO_CHAR(empno) ||  ' '  ||  ename);
      END  LOOP;
      CLOSE  emp_cursor;
    END;
    /
    
    在Cursor FOR Loops 使用子查询

    在这种情况下不需要定义cursor

    SET  SERVEROUTPUT  ON
    BEGIN
      FOR  emp_record  IN  (SELECT  employee_id,  last_name  FROM  employees  WHERE  department_id  =  30)
      LOOP
        DBMS_OUTPUT.PUT_LINE(  emp_record.employee.employee_id  ||  ' '  emp_record.last_name);
      END  LOOP;
    END;
    /
    
    带参数的Cursor
    • 语法
    CURSOR  cursor_name
      [(parameter_name  datatype,  ...)]
    IS
      select_statement;
    
    OPEN  cursor_name(parameter_value, ...);
    

    在cursor打开执行查询的时候,将参数传递给cursor。每次打开一个显式cursor,都可以传入不同的参数集合。

    • 实例
    SET  SERVEROUTPUT  ON
    BEGIN
      CURSOR  emp_cursor  (deptno  NUMBER)  IS  
        SELECT  employee_id,  last_name
        FROM  employees
        WHERE  department_id  =  deptno;
        dept_id  NUMBER;
        lname  VARCHAR2(15);
    BEGIN
      OPEN  emp_cursor(10);
      ...
      CLOSE  emp_cursor;
      OPEN  emp_cursor(20);
    
    • tip
      假设你想查询包含dept的参数,但记不清全拼了,可以按照如下方式进行查询
    show parameter dept
    

    FOR UPDATE 语句

    • 语法
    SELECT...
    FROM
    FOR  UPDATE  [OF  column_referene][NOWAIT  |  WAIT  n];
    

    在访问数据的时候对数据行加锁,以便后继的DML操作。NOWAIT的情况下,如果无法获得锁就报错;WAIT N就是可以等待n秒。加上OF column_reference并不是必须的,但是有利于代码可读性和维护性。

    锁的释放和Cursor是否关闭没有关系,需要显式的执行commit。

    WHERE CURRENT 语句

    • 语法
    WHERE  CURRENT  OF  cursor;
    

    使用 WHERE CURRENT OF 语句指向 explicit cursor 则操作当前行:

    UPDATE  employees
      SET  salary =  ...
      WHERE  CURRENT  OF  emp_cursor;
    

    相关文章

      网友评论

        本文标题:Oracle SQL 学习笔记20 - Cursor 2

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