end; declare cursor mycur(v_dno emp.deptno%type) is select sal,job from emp where deptno = v_dno; v_sal emp.sal%type; v_job emp.job%type; begin open mycur(&dno); loop fetch mycur into v_sal,v_job; exit when mycur%notfound; dbms_output.put_line(v_sal||' '||v_job); end loop; close mycur; end; 隐式游标: Oracle中select、insert、delete,update语句,在执行时Oracle会为之自动产生一个游标 游标名为SQL,此游标是由Oralce自动声明、打开、提取和关闭,用户不需要任何操作。 SQL%isopen:永远都是false,因为自动操作此属性无意义。 SQL%found=true SQL%notfound=false select: insert: delete: update:
有返回的数据行 是插入成功的 删除成功的 更新成功的
SQL%rowcount=Number select:返回的数据行数 insert:是插入数据行数 delete:删除的数据行数 update:更新的数据行数
隐式游标广泛的应用于PL/SQL编程中,用于检查DML操作的状态 范例:
1、 输入部门号和工资的增量,修改员工的工资,并输出是否修改成功,共修改了几个员工。 2、 通过输入员工编号、姓名和部门号添加新员工,保证每一个添加都成功,并正确提示用
户。
异常处理(Exception):
程序的错误类型:
1、编译类型错误:
用户误输入,或者其他与用户编程能力相关的语法错误。 此类错误可以避免,提高编程能力、借助开发工具。 2、运行时错误:
程序本事在语法上没有错误,很多时候都是能够正常运行的
有些时候因为用户提供的数据的问题或者网络、硬件等问题,而使程序不能够正
常运行的错误
这种错误依赖于用户的输入和环境配置,因此很难完全避免
在程序中可以根据各种类型的错误,做相应的处理——异常处理
语法:
DECLARE
... BEGIN ... 执行部分 Exception
When 异常名称1 [or 异常名称2?] then 语句段1 When 异常名称3 [or 异常名称4?] then 语句段2
When others then --除了1、2、3、4这4个异常以外的所有异常
语句段3
End;
Others:定义在异常处理部分没有处理的任何一个已知异常
异常名称:是一个名字,当此异常被引发,以异常名作为的表达式取true
异常的引发方式:
1、 显式引发:raise 异常名; declare
v_inc number(6,2); v_empno int;
e_test exception; --定义 begin
v_empno := &empno; v_inc := &increment; if v_inc > 1000 then raise e_test; --引发 end if;
update emp set sal=sal+v_inc where empno=v_empno; commit; exception
when e_test then –捕获
dbms_output.put_line('e_test异常被引发了');
end;
2、错误引发:这种形式,无需用户干预,只要是这个异常对应的错误发生了,此异常就自动引发
begin
insert into emp(empno,ename,deptno)
values(&empno,&ename,&deptno); commit; exception
when dup_val_on_index then –此异常只有捕获,没有定义和引发,即预定义的异常 dbms_output.put_line('员工编号不能重复'); end;
dup_val_on_index
=== -1
异常类型:
1、预定义异常 == 错误引发(内置错误—引发—内置异常) 2、用户自定义异常:
1、显式引发(raise引发) 2、错误引发
1、由Oracle内置错误引发(内置错误—引发—自定义的异常) 2、由用户自定义错误引发(自定义错误—引发—自定义异常)
预定义异常
Dup_val_on_index (-1)
试图在一个具有唯一约束的列中插入重复的值 Case_not_found(-6592):
case中没有必须的when子句,且没有包含else子句 declare a int; begin a := &a;
case a
when 1 then null; when 2 then null; end case; exception
when case_not_found then
dbms_output.put_line(SQLERRM); -- SQLERRM : SQL Error Message,获得错误消息 end;
No_data_found(-1403): select into语句没有返回任何数据 declare
v_sal number(6,2); v_empno int; begin
v_empno := &empno;
select sal into v_sal from emp where empno=v_empno; exception
when no_data_found then
dbms_output.put_line(SQLERRM);
end;
Too_many_rows (-1422):select into返回多行数据 declare
v_sal number(6,2); v_deptno int; begin
v_deptno := &deptno;
select sal into v_sal from emp where deptno=v_deptno; exception
when too_many_rows then dbms_output.put_line(SQLERRM); end;
Value_error:
发生算法、转换、截断或者大小约束错误 Zero_divide:
发生0除错误 Invalid_number:
字符串转换为数字失败(SQL 语句中)
declare v_a int; v_b char(10); begin
v_a := &a; v_b := &b;
update emp set sal=v_b where empno =v_a; commit;
exception
when invalid_number then
dbms_output.put_line(SQLERRM); end;
VALUE_ERROR
字符串转换为数字失败(PL/SQL中) declare
v_a int;
v_b number(6,2); begin v_a := &a; v_b := &b;
update emp set sal=v_b where empno =v_a; commit;
exception
when value_error then
dbms_output.put_line(SQLERRM);
end;
自定义异常——1:显式引发的与错误无关的异常
Declare Exception_name exception; --声明异常 …… Begin
……
Raise Exception_name; --引发(抛出)异常 …… Exception
when Exception_name then -- 捕获异常 ……
自定义异常——2由Oracle内置错误引发(内置错误——自定义的异常)
1、声明异常
Exception_name exception; 2、把异常与Oracle错误关联
PRAGMA EXCEPTION_INIT(exception_name,oracle_error_number); 处理外键错误的异常
declare
v_empno emp.empno%type; v_ename emp.ename%type; v_deptno emp.deptno%type; e_notnull exception;
e_fk exception;
pragma exception_init(e_notnull,-1400); pragma exception_init(e_fk,-2291); begin
v_empno:=&empno; v_ename:=&ename; v_deptno:=&deptno;
insert into emp(empno,ename,deptno) values(v_empno,v_ename,v_deptno); if SQL%found then
dbms_output.put_line('OK'); commit; else
dbms_output.put_line('ERROR'); end if; exception
when dup_val_on_index then --捕获预定义异常 dbms_output.put_line('此员工编号已经存在');