PL/SQL 会为程序中执行的每一条UPDATE,DELETE,INSERT 语句使用一个隐式游标。隐式游标有SQL%FOUND,SQL%NOTFOUND,SQL%ROWCOUNT三个属性,这些属性用于控制程序流程或者了解程序的状态。
当运行DML语句时,PL/SQL打开一个内建游标并处理结果,游标是维护查询结果的内存中的一个区域,游标在运行DML语句时打开,完成后关闭。隐式游标只使用SQL%FOUND,SQL%NOTFOUND,SQL%ROWCOUNT三个属性。SQL%FOUND,SQL%NOTFOUND是布尔值,SQL%ROWCOUNT是整数值。
1. SQL%FOUND和SQL%NOTFOUND
在执行任何DML语句前SQL%FOUND和SQL%NOTFOUND的值都是NULL,在执行DML语句后,SQL%FOUND的属性值将是:
a. TRUE :INSERT
b. TRUE :DELETE和UPDATE,至少有一行被DELETE或UPDATE.
c. TRUE :SELECT INTO至少返回一行
当SQL%FOUND为TRUE时,SQL%NOTFOUND为FALSE。
2. SQL%ROWCOUNT
在执行任何DML语句之前,SQL%ROWCOUNT的值都是NULL,对于SELECT INTO语句,如果执行成功,SQL%ROWCOUNT的值为1,如果没有成功,SQL%ROWCOUNT的值为0,同时产生一个异常NO_DATA_FOUND.
3. SQL%ISOPEN
SQL%ISOPEN是一个布尔值,如果游标打开,则为TRUE, 如果游标关闭,则为FALSE.对于隐式游标而言SQL%ISOPEN总是FALSE,这是因为隐式游标在DML语句执行时打开,结束时就立即关闭。
例子:
Name Null? Type
----------------------------------------------------------------
ID NOT NULL NUMBER(9)
SALARY NUMBER(7,2)
SUBJECT_ID NOT NULL NUMBER(3)
SUBJECT_DESCRIPTION VARCHAR2(2)
BEGIN
UPDATE teacher
SET salary = salary * 1.05
WHERE subject_id IN (101, 102, 103);
IF SQL%NOTFOUND = TRUE THEN
dbms_output.put_line(TO_CHAR(SQL%ROWCOUNT));
END IF;
END;
主要内容:
- 使用显式游标以及游标属性;
- 使用参数游标;
- 使用显式游标更新或删除数据;
- 使用游标FOR循环;
- 使用游标变量
- 使用FETCH..BULK COLLECT INTO语句和CURSOR表达式
<wbr></wbr>
1.使用显示游标
为了处理SELECT语句返回的多行数据,开发人员可以使用显式游标
使用显式游标包括定义游标、打开游标,提取数据和关闭游标。
2.显式游标属性
%ISOPEN 确定游标是否已经打开
%FOUND 检查是否从结果集中提取到了数据
%NOTFOUND<wbr>如果没有数据提取了,就返回TRUE</wbr>
%ROWCOUNT 用于返回到当前行为止已经提取到的实际行数
<wbr></wbr>
3.显式游标使用示例
示例①
DECLARE
CURSOR emp_cursor IS
SELECT ename,sal FROM emp WHERE deptno=10;
v_ename emp.ename%TYPE;
v_sal emp,sal%TYPE;
BEGIN
OPEN emp_cursor;
LOOP
FETCH emp_cursor INTO v_ename,v_sal;
EXIT WHEN emp_cursor%NOTFOUND;
dbms_output.put_line(v_ename||v_sal);
END LOOP;
CLOSE emp_cursor;
END;
<wbr></wbr>
②在显式游标中,使用FETCH...BULK COLLECT INTO语句提取所有数据
DECLARE
CURSOR emp_cursor IS
SELECT ename FROM emp WHERE deptno=10;
TYPE ename_table_type IS TABLE OF VARCHAR2(10);
ename_table ename_table_type;
BEGIN
OPEN emp_cursor;
FETCH emp_cursor BULK COLLECT INTO ename_table;
FOR i IN 1..ename_table.COUNT LOOP
dbms_output.put_line(ename_table(i));
END LOOP;
CLOSE emp_cursor;
END;
/
<wbr></wbr>
③在显式游标中使用FETCH ..BULK COLLECT INTO..LIMIT语句提取部分数据
下面以每次提取5行数据为例,说明使用LIMIT子句限制提取行的方法
DECLARE
TYPE name_array_type IS VARRAY(5) OF VARCHAR2(10);
name_array name_array_type;
CURSOR emp_cursor IS SELECT ename FROM emp;
rows INT:=5;
v_count INT:=0;
BEGIN
OPEN emp_cursor;
LOOP
FETCH emp_cursor BULK COLLECT INTO name_array
LIMIT rows;
dbms_output.put('雇员名');
FOR i IN 1..(emp_cursor%ROWCOUNT-v_count) LOOP
dbms_output.put_line(name_array(i)||' ');
END LOOP;
dbms_output.put_line;//换行
v_count:=emp_cursor%ROWCOUNT;
EXIT WHEN emp_cursor%NOTFOUND;
END LOOP;
END;
/
<wbr></wbr>
④使用游标属性
DECLARE
CURSOR emp_cursor IS
SELECT ename FROM emp WHERE deptno=10;
TYPE ename_table_type IS TABLE OF VARCHAR2(10);
ename_table ename_table_type;
BEGIN
IF NOT emp_cursor%ISOPEN THEN --如果游标未打开,则打开游标
OPEN emp_cursor;
END IF;
FETCH emp_cursor BULK COLLECT INTO ename_table;
dbms_output.put_line('提取的总行数:'||emp_cursor%ROWCOUNT);--显示总计行数
CLOSE emp_cursor;
END;
/
<wbr></wbr>
⑤基于游标定义记录变量
使用%ROWTYPE属性不仅可以基于表和视图定义记录变量,也可以基于游标定义记录变量。
当基于游标定义记录变量时,记录成员名实际就是SELECT语句的列名或列别名。为了简化显式游标的数据处理,建议开发人员使用记录变量存放游标数据。
DECLARE
CURSOR emp_cursor IS SELECT ename,sal FROM emp;
emp_record emp_cursor%ROWTYPE;
BEGIN
OPEN emp_cursor;
LOOP
FETCH emp_cursor INTO emp_record;
EXIT WHEN emp_cursor%NOTFOUND;
dbms_output.put_line('雇员名'||emp_record.ename||'雇员工资'||emp_record.sal);
END LOOP;
CLOSE emp_cursor;
END;
/
转自 http://blog.csdn.net/yinghuashihun/article/details/6859537