13. END LOOP;
14. ELSE
15. DBMS_OUTPUT.PUT_LINE('用户信息:游标没有打开!'); 16. END IF;
17. CLOSE emp_cursor; 18. END;
执行结果为: Sql代码
1. 1-SMITH 2. 2-ALLEN 3. 3-WARD
4. PL/SQL 过程已成功完成。
说明:本例使用emp_cursor%ISOPEN判断游标是否打开;使用emp_cursor%ROWCOUNT获得到目前为止FETCH语句返回的数据行数并输出;使用循环来获取数据,在循环体中使用FETCH语句;使用emp_cursor%NOTFOUND判断FETCH语句是否成功执行,当FETCH语句失败时说明数据已经取完,退出循环。
【练习1】去掉OPEN emp_cursor;语句,重新执行以上程序。
游标参数的传递
【训练1】 带参数的游标。 Sql代码
1. SET SERVEROUTPUT ON 2. DECLARE
3. V_empno NUMBER(5); 4. V_ename VARCHAR2(10);
5. CURSOR emp_cursor(p_deptno NUMBER, p_job VARCHAR2) IS 6. SELECT empno, ename FROM emp
7. WHERE deptno = p_deptno AND job = p_job; 8. BEGIN
9. OPEN emp_cursor(10, 'CLERK');
10. LOOP
11. FETCH emp_cursor INTO v_empno,v_ename; 12. EXIT WHEN emp_cursor%NOTFOUND;
13. DBMS_OUTPUT.PUT_LINE(v_empno||','||v_ename); 14. END LOOP; 15. END;
执行结果为:
Sql代码
1. 7934,MILLER
2. PL/SQL 过程已成功完成。
说明:游标emp_cursor定义了两个参数:p_deptno代表部门编号,p_job代表职务。语句OPEN emp_cursor(10, 'CLERK')传递了两个参数值给游标,即部门为10、职务为CLERK,所以游标查询的内容是部门10的职务为CLERK的雇员。循环部分用于显示查询的内容。 【练习1】修改Open语句的参数:部门号为20、职务为ANALYST,并重新执行。
也可以通过变量向游标传递参数,但变量需要先于游标定义,并在游标打开之前赋值。对以上例子重新改动如下:
【训练2】 通过变量传递参数给游标。 Sql代码
1. SET SERVEROUTPUT ON 2. DECLARE
3. v_empno NUMBER(5); 4. v_ename VARCHAR2(10); 5. v_deptno NUMBER(5); 6. v_job VARCHAR2(10);
7. CURSOR emp_cursor IS
8. SELECT empno, ename FROM emp
9. WHERE deptno = v_deptno AND job = v_job; 10. BEGIN
11. v_deptno:=10; 12. v_job:='CLERK'; 13. OPEN emp_cursor; 14. LOOP
15. FETCH emp_cursor INTO v_empno,v_ename; 16. EXIT WHEN emp_cursor%NOTFOUND; 17. DBMS_OUTPUT.PUT_LINE(v_empno||','||v_ename); 18. END LOOP; 19. END;
执行结果为: Sql代码:
1. 7934,MILLER
2. PL/SQL 过程已成功完成。
说明:该程序与前一程序实现相同的功能。
动态SELECT语句和动态游标的用法:
Oracle支持动态SELECT语句和动态游标,动态的方法大大扩展了程序设计的能力。 对于查询结果为一行的SELECT语句,可以用动态生成查询语句字符串的方法,在程序执行阶段临时地生成并执行,语法是:
execute immediate 查询语句字符串 into 变量1[,变量2...]; 以下是一个动态生成SELECT语句的例子。 【训练1】 动态SELECT查询。 Sql代码:
1. SET SERVEROUTPUT ON 2. DECLARE
3. str varchar2(100); 4. v_ename varchar2(10); 5. begin
6. str:='select ename from scott.emp where empno=7788'; 7. execute immediate str into v_ename; 8. dbms_output.put_line(v_ename); 9. END;
执行结果为: Sql代码:
1. SCOTT
2. PL/SQL 过程已成功完成。
说明:SELECT...INTO...语句存放在STR字符串中,通过EXECUTE语句执行。 在变量声明部分定义的游标是静态的,不能在程序运行过程中修改。虽然可以通过参数传递来取得不同的数据,但还是有很大的局限性。通过采用动态游标,可以在程序运行阶段随时生成一个查询语句作为游标。要使用动态游标需要先定义一个游标类型,然后声明一个游标变量,游标对应的查询语句可以在程序的执行过程中动态地说明。 定义游标类型的语句如下: TYPE 游标类型名 REF CURSOR; 声明游标变量的语句如下: 游标变量名 游标类型名;
在可执行部分可以如下形式打开一个动态游标: OPEN 游标变量名 FOR 查询语句字符串;
【训练2】 按名字中包含的字母顺序分组显示雇员信息。 输入并运行以下程序: Sql代码:
1. declare
2. type cur_type is ref cursor; 3. cur cur_type;
4. rec scott.emp%rowtype; 5. 6. 7. 8.
str varchar2(50); letter char:= 'A'; begin
loop
9. str:= 'select ename from emp where ename like ''%'||letter||'%'
''; 10. open cur for str;
11. dbms_output.put_line('包含字母'||letter||'的名字:'); 12. loop
13. fetch cur into rec.ename; 14. exit when cur%notfound;
15. dbms_output.put_line(rec.ename); 16. end loop;
17. exit when letter='Z';
18. letter:=chr(ascii(letter)+1); 19. end loop; 20. end;
运行结果为: Sql代码:
1. 包含字母A的名字: 2. ALLEN 3. 4. 5. 6.
WARD MARTIN BLAKE CLARK
7. ADAMS
8. JAMES
9. 包含字母B的名字: 10. BLAKE
11. 包含字母C的名字: 12. CLARK 13. SCOTT
说明:使用了二重循环,在外循环体中,动态生成游标的SELECT语句,然后打开。通过语句letter:=chr(ascii(letter)+1)可获得字母表中的下一个字母。
异常处理 错误处理
错误处理部分位于程序的可执行部分之后,是由WHEN语句引导的多个分支构成的。错误处理的语法如下: