隐含游标:专门处理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;