一 游标:游标(cursor)是一种PL/SQL控制结构:它可以命名一个工作区来存取该工作区的存储信息。可以非常方便的帮助我们从数据库中提取多行数据,然后可以对每一条数据进行单独处理。
1)游标的四个属性:%found 查询语句(FETCH语句)返回记录
%notfound 查询语句(FETCH语句)无返回记录,用于循环退出条件
%isopen 光标已打开标记
%rowcount FETCH已获取的记录数
2)while和for语句访问游标
3)定义带参数的游标,并访问
4)定义隐式游标,并访问
隐式游标属性
SQL%FOUND : SQL语句返回有记录
SQL%NOTFOUND : SQL语句返回无记录
SQL%ROWCOUNT : SQL语句记录总数
-----------------------------------------
eg1:while访问
declare
v_id tbl_student.studentid%type;
v_name tbl_student.studentname%type;
cursor c1 is select studentid, studentname from tbl_student where rownum <= 20;
begin
open c1;--打开游标
fetch c1 into v_id, v_name; --提取游标
while c1%found loop --使用了%found属性
dbms_output.put_line(v_id || ' ' || v_name);
fetch c1 into v_id, v_name;
end loop;
close c1;--关闭游标
end;
---------------------------------------------
eg2:for访问
declare
cursor c1 is select studentid, studentname from tbl_student where rownum <= 20;
begin --使用for时,游标不用打开、不用关闭、不用提取。直接用a1访问表的字段。a1不是游标,可以认为是指向游标的指针。
for a1 in c1 loop
dbms_output.put_line(a1.studentid || ' ' || a1.studentname);
end loop;
end;
-----------------------------------------------
eg3:for访问带参数的游标
declare
cursor c1(v_num number, v_sex number) is --带参数的游标
select studentid, studentname, sex from tbl_student where (rownum <= v_num) and (sex = v_sex);
begin
for a1 in c1(10, 2) loop --定义带参数的游标
dbms_output.put_line(a1.studentid || ' ' || a1.studentname || ' ' || a1.sex);
end loop;
end;
------------------------------------------------------
eg4:while访问带参数的游标
declare
v_id tbl_student.studentid%type;
v_name tbl_student.studentname%type;
v_sex tbl_student.sex%type;
cursor c1(v_num number, v_sex number) is
select studentid, studentname, sex from tbl_student where (rownum <= v_num) and (sex = v_sex);
begin
open c1(30, 1);
fetch c1 into v_id, v_name, v_sex; --提取游标
while c1%found loop --使用了%found属性
dbms_output.put_line(v_id || ' ' || v_name || ' ' || v_sex);
fetch c1 into v_id, v_name, v_sex;
end loop;
close c1;
end;
--------------------------------------------------------
eg5:for访问隐式游标
declare
begin
for a1 in (select studentid, studentname, sex from tbl_student where rownum <= 20) loop
dbms_output.put_line(a1.studentid || ' ' || a1.studentname || ' ' || a1.sex);
end loop;
end;
二 异常: 在PL/SQL中一个警告或错误的情形都被叫做异常。我们可以编写一段叫异常处理器的独立程序来控制出发异常。当一个异常被触发的时候,当前的块就会转到异常处理部分。
异常类型:
系统预定义的异常: 是由PL/SQL运行过程中,系统自动产生的信息。
用户定义异常: 是用户根据需要,自己定义使用的异常,执行时由用户自己引起。
预定义的异常类型:
CURSOR_ALREADY_OPEN : 光标已经存在
VALUE_ERROR : 值错误
NO_DATA_FOUND : 没有找到数据
INVALID_NUMBER : 无效数值
TOO_MANY_ROWS : 返回太多的行
ZERO_DIVIDE : 被0除
INVALID_CURSOR : 无效光标
--------------------------------------------------------
eg1:系统预定义异常:NO_DATA_FOUND使用示例。
declare
v_studentid tbl_student.studentid%type;
begin
select studentid into v_studentid from tbl_student where studentname='dddddd';
exception
when NO_DATA_FOUND then
dbms_output.put_line('exception:no_data_found');
when others then
dbms_output.put_line('error!');
end;
自定义异常说明:
用户定义的异常必须在DECLARE段中说明,在Begin段中用RAISE引起,在EXCEPTION段中使用。
-----------------------------------------------------------
eg1:用户自定义异常
declare
my_exception exception;--用户自定义异常
v_num number := 0;
begin
select count(*) into v_num from tbl_student where studentname='yyyy';
if v_num = 0 then --如果不存在符合条件的记录,引发异常
raise my_exception;
else
dbms_output.put_line('存在这个姓名的学生。'); --如果触发了异常就不会执行此语句
end if;
exception
when my_exception then
dbms_output.put_line('该学生不存在。');
when others then
dbms_output.put_line('error!');
end;
三 事务处理
事务概念:
数据库中的重要机制,确保数据完整性和并发处理的能力,它将一条或者一组sql语句当成一个逻辑上的单元,用于保障这些语句要么都成功,要么都失败。
事务的特性:
1)原子性:事务中的操作,要么全做成,要么都不做,事务是不可拆分的
2)一致性:单独运行的事务,必须保证保持数据库的一致状态
3)隔离性:多个并发事务之间不能相互干扰
4)永久性:一旦事务成功完成(Commit),它对数据库的操作是持久的
开始于第一个执行的语句:DML。
结束于以下几种情况:
1)显示执行commit/rollback;
2)执行于DDL语句或者DCL时候事物会自动提交,再rollback提交不回去了
3)正常断开的时候:
如exit ,transaction会自动提交
非正常断开的时候,如直接关闭transaction会自动回滚。
-----------------------------------------------------
eg1:事务处理示例
declare
begin
update tbl_accountinfo set name = 'lucy' where id = 2;
savepoint sp1; --定义一个事务点
delete from tbl_accountinfo where id = 2;
rollback to savepoint sp1; --回滚到事务点sp1。
commit; --提交。只执行了修改,没执行删除。事务回滚了。
exception
when others then
dbms_output.put_line('error!');
end;
---------------------------------------------------------
eg2:
declare
v_i scott.emp.ename%type;
begin
update scott.emp set ename = 'macle3' where empno = 7369;
savepoint sp1;
select ename into v_i from scott.emp where empno=1114465461; --没有符合要求的记录
if sql%notfound then --如果此事务不作if判断,依然会执行下面的rollback,commit。上面的select语句不会报错。
dbms_output.put_line('data_not_found!');
else
dbms_output.put_line('ok!');
end if;
rollback to savepoint sp1;
commit;
exception
when no_data_found then
dbms_output.put_line('data_not_found!');
end;
-----------------------------------------------------------------
eg3:
declare
v_i scott.emp.ename%type;
begin
update scott.emp set ename = 'macle3' where empno = 7369;
savepoint sp1;
select ename into v_i from scott.emp where empno=1114465461;--此时会跳到异常处理。事务全部执行不成功。
commit;
exception
when no_data_found then
dbms_output.put_line('data_not_found!');
end;