隐含游标:专门处理SELECT INTO、INSERT、UPDATE以及DELETE语句。
 显示游标:用于处理多行的SELECT语句。
 当在PL/SQL块中执行INSERT、UPDATE及DELETE语句时,为了取得DML语句作用的结果,需要使用SQL游标属性。
 第一,游标的4种属性
  1. SQL%ISOPEN
 该属性永远都是false,没有实际意义。
  2. SQL%FOUND
 语句是否操作成功。当SQL语句有作用行时为TRUE.
  3. SQL%NOTFOUND
 LOOP
  FETCH  emp_cursor  INTO   v_name, v_deptno;
 EXIT  WHEN  emp_cursor%NOTFOUND;
  ...
 END LOOP;
  
  4. SQL%ROWCOUNT
 返回SQL语句所作用的总计行数。
 该属性用于返回已提取的实际行数。
  
 第二,显示游标专用于处理SELECT语句返回的多行数据。
   CURSOR  cursor_name  IS  select_statement;
   open  cursor_name;
   FETCH  cursor_name  INTO  var1[, var2, ...];
   CLOSE  cursor_name;
 例子:
 DECLARE
   CURSOR category_cursor
   IS
      SELECT *
        FROM tb_out_service t
       WHERE t.servicename LIKE '长沙%';  
   TYPE category_table_type IS TABLE OF tb_out_service%ROWTYPE
      INDEX BY BINARY_INTEGER;  
   category_table   category_table_type;
   i                INT;
BEGIN
   OPEN category_cursor;  
   LOOP
      i := category_cursor%ROWCOUNT + 1;  
      FETCH category_cursor
       INTO category_table (i);  
      EXIT WHEN category_cursor%NOTFOUND;
      DBMS_OUTPUT.put_line (   RPAD (category_table (i).serviceid, 30)
                            || '  '
                            || category_table (i).servicename
                           );
   END LOOP;  
   CLOSE category_cursor;
END;  
 
 第三,游标FOR循环
 语法:
 FOR  record_name  IN  cursor_name  LOOP
  statement;
 ...
 END  LOOP;
 注意:当使用游标FOR循环时,既可以在定义部分定义游标,也可以直接在FOR循环中使用SELECT语句。
  
 第四,参数游标
 CURSOR cursor_name(parameter_name datatype) is select_statement;
 OPEN cursor_name(parameter_value)
 注意:
 定义参数只能指定数据类型,不能指定长度。
 另外,应该在游标的select语句的where子句中引用游标参数,否则失去了定义参数游标的意义。
 ---------------------------------------------------------------------------------------------------------------------
 DECLARE
   CURSOR category_cursor (NAME VARCHAR2)
   IS
      SELECT *
        FROM tb_out_service t
       WHERE t.servicename LIKE NAME || '%';
BEGIN
   FOR category_record IN category_cursor ('吉首')
   LOOP
      DBMS_OUTPUT.put_line (   RPAD (category_record.serviceid, 30)
                            || '  '
                            || category_record.servicename
                           );
   END LOOP;
END;  
 
 第五,更新或删除游标行
 语法:
 CURSOR cursor_name IS select_statement
  FOR UPDATE [OF column_reference]  [NOWAIT];
 UPDATE table_name SET column=..  WHERE CURRENT OF cursor_name;
 DELETE FROM table_name WHERE CURRENT OF cursor_name;
  
 注意:
  1. OF子句的格式:column_reference为table_name.column_name
 2. WHERE CURRENT OF cursor_name, 更新或者删除游标所在行的数据。
  3. 在使用游标更新或删除数据时,定义游标必须带有FOR  UPDATE子句,并且在更新或者删除游标时必须带有WHERE CURRENT OF 子句。
 当查询语句涉及到多张表时,如果不带有OF子句,会在多张表上同时加锁,如果只在特定的表上加锁,需要带有OF子句。
  
 DECLARE
   CURSOR category_cursor (NAME VARCHAR2)
   IS
      SELECT        *
               FROM tb_out_service t
              WHERE t.servicename LIKE NAME || '%'
      FOR UPDATE OF t.querystr;  
   v_name   CONSTANT VARCHAR2 (20) := '长沙';
BEGIN
   FOR category_record IN category_cursor (v_name)
   LOOP
      IF INSTR (category_record.servicename, v_name || '——') <> 1
      THEN
         DBMS_OUTPUT.put_line (   'delete: '
                               || RPAD (category_record.serviceid, 30)
                               || '  '
                               || category_record.servicename
                              );  
         DELETE FROM tb_out_service
               WHERE CURRENT OF category_cursor;
      ELSE
         DBMS_OUTPUT.put_line (   'upate: '
                               || RPAD (category_record.serviceid, 30)
                               || '  '
                               || category_record.servicename
                              );  
         UPDATE tb_out_service t
            SET t.querystr = v_name || '——' || t.servicename
          WHERE CURRENT OF category_cursor;
      END IF;
   END LOOP;
END; 
 
 第六, 游标变量
  游标变量是基于REF CURSOR类型所定义的变量,它实际上是指向内存地址的指针。显式游标只能定义静态游标,而游标变量可以在打开时指定其所对应的SELECT语句,从而实现动态游标。
   TYPE  ref_type_name  IS  REF  CURSOR  [RETURN  return_type];
 cursor_variable  ref_type_name;
   OPEN  cursor_name  FOR  select_statement;
   FETCH  cursor_variable  INTO  var1[, var2, ...];
   CLOSE  cursor_variable;
 注意:
  不能在远程子程序中使用游标变量。
 当指定子查询时,不能带有FOR UPDATE子句。
 当指定RETURN子句时,返回类型必须使用PL/SQL记录类型。
 例子:
 DECLARE
   TYPE category_cursor_type IS REF CURSOR
      RETURN tb_out_service%ROWTYPE;  
   category_cursor   category_cursor_type;
   category_record   tb_out_service%ROWTYPE;
   v_name   CONSTANT VARCHAR2 (40)            := '长沙';
BEGIN
   OPEN category_cursor FOR
      SELECT *
        FROM tb_out_service t
       WHERE t.servicename LIKE v_name || '%';  
   LOOP
      FETCH category_cursor
       INTO category_record;  
      EXIT WHEN category_cursor%NOTFOUND;
      DBMS_OUTPUT.put_line (   RPAD (category_record.serviceid, 30)
                            || '  '
                            || category_record.servicename
                           );
   END LOOP;
END;