触发器的定义: q触发器是当特定事件出现时自动执行的存储过程
q特定事件可以是执行更新的DML语句和DDL语句 q触发器不能被显式调用 q触发器的功能:q自动生成数据 q自定义复杂的安全权限 q提供审计和日志记录 q启用复杂的业务逻辑 触发器的语法: CREATE [OR REPLACE] TRIGGER trigger_name AFTER | BEFORE | INSTEAD OF [INSERT] [[OR] UPDATE [OF column_list]] [[OR] DELETE] ON table_or_view_name [REFERENCING {OLD [AS] old / NEW [AS] new}] [FOR EACH ROW] [WHEN (condition)] pl/sql_block;触发器由三部分组成: q触发器语句(事件) q定义激活触发器的 DML 事件和 DDL 事件 q触发器限制 q执行触发器的条件,该条件必须为真才能激活触发器 q触发器操作(主体) q包含一些 SQL 语句和代码,它们在发出了触发器语句且触发限制的值为真时运行 |
| ? |
触发器按执行次序分为:before触发器、after触发器
before触发器:
after触发器:
for each row:
| create table student (id number (10 ),name varchar2 (20 ),age number( 10)); insert into student values( 1, '张三',20); insert into student values( 2, '李四',25); insert into student values( 3, '王五',30); create or replace trigger trigger1 after update --after触发器,并且针对于更新操作 on student --触发器针对哪张表 for each row -- 添加了 begin dbms_output.put_line('更新了' ); end; -- ORA-04089: 无法对 SYS 拥有的对象创建触发器 SQL >connect hr/ hr@ jiagulun update student s set s.age = s.age +5 ; SQL> set serverout on; SQL> update student s set s.age = s.age +5 ; 更新了--触发器触发了 更新了--触发器触发了 更新了--触发器触发了 3 rows updated --更新了三行触发了三次 SQL> create or replace trigger trigger1 after update on student SQL> update student s set s.age = s.age +5 ; 更新了--触发器触发了 3 rows updated --更新了三行触发了一次 SQL> 通过上面的测试可以得出: 1.对于sys用户所拥有的对象是不能建立触发器的。 2.for each row: 1.假如添加了说明是行级别的触发器,每行的更新都会触发。 2. 假如没添加就是表级别的触发器,所有的更新行只会触发一次。 |
:new 和 :old的区别:
| :new 和sqlserver中的inserted :old 和sqlserver中的deleteed 如果在触发器的plsql内使用了:new 和 :old,就必须使用行级触发器也就是for each row 因为:new和:old是指向某行记录的指针,假如是表级别的触发器这两个指针不知道确定指向哪行记录 这样就会产生歧义了 当执行insert 的时候: :new存在 :old不存在。当执行delete 的时候: :new不存在 :old存在。当执行update 的时候: :new存在 :old存在。 当一个update被执行的时候: oracle是先删除记录行,所以old是需要的 oracle再insert记录行,所以new是需要的 create or replace trigger trigger2 before update on student for each row begin if :old.age > 20 or :new.age < 30 then raise_application_error (-20001 ,'大于20岁的学生不需要更新,而且更新后的年龄不能大于30' ); end if; end; SQL> update student s set s.age = s.age + 10; update student s set s.age = s.age + 10 --ORA-20001: 大于20岁的学生不需要更新,而且更新后的年龄不能大于30 --ORA-06512: 在 "HR.TRIGGER2", line 3 --ORA-04088: 触发器 'HR.TRIGGER2' 执行过程中出错 create or replace trigger trigger2 before update on student --for each row 使用了new或old就必须使用行级触发器 begin if :old.age > 20 or :new.age < 30 then raise_application_error (-20001 ,'大于20岁的学生不需要更新,而且更新后的年龄不能大于30' ); end if; end; --ORA-04082: NEW 或 OLD 引用不允许在表级触发器中 SQL> 通过上面的操作可以发现: 1. NEW 或 OLD 引用不允许在表级触发器中 2. 在update中既有new 也有 old 3. 在触发器中不能使用alter、create、事务回滚、 create or replace trigger trigger3 --ORA-04084: 无法更改此触发器类型的 NEW 值 create or replace trigger trigger3 before/after delete on student for each row begin if :old.age > 0 then |
触发器的类型:
instead of触发器:
| SQL> create view stu_add_view 2 as select s.id, s.name, s.age, a.zz from student s inner join address a 3 on s.id = a.xh; View created SQL> select * from stu_add_view; ID NAME AGE ZZ ----------- -------------------- ----------- ---------- 2 李四 40 郑州 1 张三 35 开封 3 王五 45 洛阳 SQL> update stu_add_view sav set sav.zz = '江西' where sav.name = '王五'; update stu_add_view sav set sav.zz = '江西' where sav.name = '王五'; --ORA-01779: 无法修改与非键值保存表对应的列 --对于上面的错误,可以通过触发器来解决: create or replace trigger trigger4 instead of update on stu_add_view for each row declare xh3 number (10 );--变量的声明不要和列名相同,因为会出现下面问题: begin select s.id into xh3 from student s where s.name = |