实验07 游标存储过程触发器.docx
《实验07 游标存储过程触发器.docx》由会员分享,可在线阅读,更多相关《实验07 游标存储过程触发器.docx(13页珍藏版)》请在冰豆网上搜索。
![实验07 游标存储过程触发器.docx](https://file1.bdocx.com/fileroot1/2022-11/16/a7028938-5c02-440f-9bf6-4fcc20601d0b/a7028938-5c02-440f-9bf6-4fcc20601d0b1.gif)
实验07游标存储过程触发器
实验七游标,存储过程,触发器
Sqlplus/nolog
connscott/tiger
declare
cursormycuris
select*fromemp;
myrecordemp%ROWTYPE;
begin
openmycur;
fetchmycurintomyrecord;
whilemycur%FOUNDloop
dbms_output.put_line(myrecord.empno||’,’||myrecord.ename);
fetchmycurintomyrecord;
endloop;
closemycur;
end;
/
savec:
\plsql_cursor01.txt
带参数的游标,%NOTFOUND属性
declare
cursorcur_para(idvarchar2)is
selectenamefromempwhereempno=id;
t_nameemp.ename%TYPE;
begin
opencur_para(‘7369’);
loop
fetchcur_paraintot_name;
exitwhencur_para%NOTFOUND;
dbms_output.put_line(t_name);
endloop;
closecur_para;
end;
/
用FOR循环实现
declare
cursorcur_para(idvarchar2)is
selectenamefromempwhereempno=id;
begin
dbms_output.put_line(‘*******结果*************’);
forcurincur_para(‘7369’)loop
dbms_output.put_line(cur.ename);
endloop;
end;
/
%ISOPEN属性
declare
t_nameemp.ename%TYPE;
cursorcur(idvarchar2)is
selectenamefromempwhereempno=id;
begin
ifcur%ISOPENthen
dbms_output.put_line(‘游标已打开’);
else
opencur(‘7369’);
endif;
fetchcurintot_name;
closecur;
dbms_output.put_line(t_name);
end;
/
%ROWCOUNT属性
declare
t_namevarchar2(10);
cursormycuris
selectdnamefromdept;
begin
openmycur;
loop
fetchmycurintot_name;--一开始可以不要这句试下,然后要这一句试下。
exitwhenmycur%NOTFOUNDormycur%NOTFOUNDisnull;
dbms_output.put_line(‘游标mycur的rowcount是:
’||mycur%ROWCOUNT);
endloop;
closemycur;
end;
/
利用游标修改数据
declare
cursorcuris
selectdnamefromdeptforupdate;
textvarchar2(10);
begin
opencur;
fetchcurintotext;
whilecur%FOUNDloop
updatedeptsetdname=dname||’_t’wherecurrentofcur;--判断当前行
fetchcurintotext;
endloop;
closecur;
end;
/
验证数据是否发生了变化
select*fromdept;
rollback;数据回滚
隐式游标的使用
begin
forcurin(selectdnamefromdept)loop
dbms_output.put_line(cur.dname);
endloop;
end;
/
看不到游标的申明,打开和关闭。
数据量很大时不建议使用游标。
过程
createorreplaceproceduremyproc(idvarchar2(10))
如果编译错会提示,可以查询错误信息
showerror
showerrorproceduremyproc;
savec:
\plsql_proc01.txt
将第一句改为
createorreplaceproceduremyproc(idvarchar2)–默认为IN
is
namevarchar2(10);
begin
selectenameintonamefromempwhereempno=id;
dbms_output.put_line(name);
endmyproc;--名称为可选
/
执行
declare
tidvarchar2(10);
begin
tid:
=’7369’;
myproc(tid);
end;
/
也可以
begin
myproc(‘7369’);
end;
/
甚至可以单独执行存储过程
executemyproc(‘7369’);
但要求存储过程不带参数,或参数只能是IN,且为常量
begin
executemyproc(‘7369’);--这是错误的
end;
/
输出参数的使用
createorreplaceproceduremyproc2(idvarchar2,nameoutvarchar2)
is
begin
selectenameintonamefromempwhereempno=id;
end;
/
declare
tidvarchar2(10);
tnamevarchar2(10);
begin
tid:
=’7369’;
myproc2(tid,tname);
dbms_outpu.put_line(tname);
end;
触发器
可以看成一个过程,但自动完成。
当数据进行增,删,改时,可以触发。
存储在数据库中。
当事件发生时,会显式调用触发器
触发器不能带参数
比如维护表的强制性约束
数据操作元触发器
行级触发器
语句级触发器
替换触发器
数据定义元触发器
系统触发器
触发器:
事件+对象(表)+条件+执行语句体
事务介绍:
SQL>select*fromemp;
作一个删除
SQL>deletefromempwhereempno=’7876’;
SQL>commit;--语句真正的写到了数据库中
SQL>select*fromemp;
SQL>deletefromempwhereempno=’7900’;
SQL>select*fromemp;
查到是删除了。
但
SQL>rollback;
SQL>select*fromemp;
删除的又回来了。
确保事务完整性
事务的四个特性:
原子性,一致性,隔离性,永久性
事务的原子性
表的增删改都可能改变表的结果,对于一个单表而言,比如DELETE,要不删除成功,要不删除失败,
比如:
SQL>deletefromempwhereempno=’7902’;
由于本身只有一个表,所以,本身就是原子的,因为一个表无法分割,要不成功,要不失败。
事务的原子性是指对两个或两个以上的表,很可能对一个表成功,一个失败等四种可能,而这两个表中有很强的业务联系时,则进行两个表操作时,可能出现不一致的问题,
比如A转账给B,A转成功了,但B没有转成功,则会出问题。
所以,必须保证都成功,如果有一个出问题,则都回滚。
比如销售中销售的商品和库存中的商品要保持一致性,不能销售表成功了,但库存表中没有成功就不行。
将两个表看成一个逻辑上不可分割的单元,通过事务的方式来保证,这就是原子性。
可以通过触发器来完成。
事务的一致性:
保证操作前后,保证表的一致,A转3W到B,则转完后,前后要一致。
销售也是一样的。
原子性是手段,一致性是目的。
事务的隔离性
隔离性越强,并发性越差。
隔离性越差,并发性越高
隔离性有许多等级
比如:
只能读已提交的数据
SQL>deletefromemp;
SQL>select*fromemp;
看没有记录了
我们打开另一个会话框
用系统用户登录,再查该表,
SQL>select*fromemp;;
发现还有记录,即读不到未提交的信息。
commit和rollback两个事务命令
SQL>deletefromempwhereempno=’7839’;
在另一个窗口还是可以看到这个数据,因为并没有提交
SQL>commit;--写到数据文件中
在另一个窗口中就看不到了。
rollback是取消前面的功能。
比如火车票售票,两个站都读到5张,卖3张,这是不可能的。
因为没有6张。
这就通过隔离性,在没有修改完成,对方不能读进来。
SQL>select*fromemp;
SQL>updateempsetename=’sdfd’whereempno=’7839’;
SQL>select*fromemp;
但对方看不到
但如果我查到有5张,我还没有修改,对方已修改了,卖了3张。
SQL>select*fromempforupdate
则另一方不允许
updateempsetename=’adfadsf’whereempno=’7839’;
通过锁的机制来实现的,先处理的用户会加锁,处理完了才能解锁,加锁后隔离性强,但并发性差了。
比如:
SQL>updateempsetename=’qq’whereempno=’7839’;
SQL>commit;
改完提交后,另一方才能改。
永久性指提交了不能回滚,回滚后不能提交了。
因为已物理的改变了。
再修改时,另一个事务又开始了。
1.行级触发器
delete,insert,update(select由于是查询,不影响数据,所以,不会影响一致性)
SQL>select*fromemp;
SQL>select*fromdept;
实现参考完整性,将部门表中的编号改掉时,员工的部门编号也要改,可以用行级触发器来实现
SQL>createorreplacetriggerdel_deptid
afterdeleteondept
foreachrow
begin
deletefromempwheredeptno=:
old.deptno;
enddel_deptid;
/
SQL>deletefromdeptwheredeptno=’10’;
SQL>select*fromdept;
SQL>select*fromemp;
10的信息全没有了。
SQL>rollback;--回滚
SQL>createorreplacetriggerinsert_dept
afterinsertondept
foreachrow
begin
inse