定义/声明游标的时候只是把SQL与游标关联,在open的时候才和表发生查询关系,如果有for update会有

  加锁发生,如在本例中,OPEN c_cursor后,通过debug的方式停止在'--afater open',通过

  select * from v$lock where sid in (select distinct sid from v$session where username='PLSQL')可以看到有加锁的记录,本例是以PLSQL用户登录的.在fetch的过程中,Oracle会保证一致性读,可以通过将For update去掉,在fetch的过程中在另外一个session中更新并提交数据来观察.大家可以参考我的另外一篇blog http://blog.csdn.net/kkdelta/article/details/7183981模拟了这个过程.close cursor并不会释放for update获得的锁,事务结束才释放。

  另外,先我是想用DBMS_OUTPUT.PUT_LINE和DBMS_LOCK.SLEEP配合来观察加锁和释放锁的现象,结果是DBMS_OUTPUT.PUT_LINE要在整个存储过程执行完之后才会输出,后来只好在PL/SQL Developer中通过debug的方式观察,大家要注意了。

  在sqlplus中使用游标可以用以下方式:

  variable c refcursor;

  exec open :c for SELECT ISBN, TITLE FROM BOOKS WHERE rownum < 5 FOR UPDATE;

  print c;

  rollback;

  同样exec open 的时候会加锁,后需要显示结束事务才能释放锁。

  PLSQL中还有一个称为游标变量的概念,与游标不同的是,游标变量是动态的,而游标是静态的。游标只能与指定的查询相连,即固定指向一个查询的内存处理区域,而游标变量则可与不同的查询语句相连,它可以指向不同查询语句的内存处理区域(但不能同时指向多个内存处理区域,在某一时刻只能与一个查询语句相连)。

  声明一个游标变量的需要注意的步骤:

  1、定义一个REF CURSOU数据类型,如:

  TYPE ref_cursor_type IS REF CURSOR;

  2、声明一个该数据类型的游标变量,如:

  cv_ref REF_CURSOR_TYPE;

  3、在打开的时候和一个SQL语句关联:

  OPEN cursor_variable_name

  FOR select_statement;

  后面这和游标的使用相同了,如下例:

DECLARE
    TYPE refcur_type IS REF CURSOR;
    book_refcur refcur_type ;
    v_isbn varchar2(100);
    v_title   varchar2(100);
BEGIN
    OPEN book_refcur FOR
    SELECT ISBN, TITLE FROM BOOKS WHERE rownum<3;
 
    FETCH book_refcur INTO v_isbn,v_title;
    WHILE book_refcur%FOUND LOOP
       DBMS_OUTPUT.PUT_LINE(v_isbn||': '||v_title);
    FETCH book_refcur INTO v_isbn,v_title;
    END LOOP;
    CLOSE book_refcur;
  
    -- open cursoe with another sql statement
    DBMS_OUTPUT.PUT_LINE('------- open cursoe with another sql statement');
    OPEN book_refcur FOR
    SELECT ISBN, category FROM BOOKS WHERE rownum<3;
 
    FETCH book_refcur INTO v_isbn,v_title;
    WHILE book_refcur%FOUND LOOP
       DBMS_OUTPUT.PUT_LINE(v_isbn||': category is: '||v_title);
    FETCH book_refcur INTO v_isbn,v_title;
    END LOOP;
    CLOSE book_refcur;  
END;