触发器
- 触发器组成
1、触发事件
DML或DDL语句。
2、触发时间
是在触发事件发生之前(before) 还是之后(after) 触发
3、触发操作
使用PL/SQL块进行相应的数据库操作
4、触发对象
表、视图、模式、数据库
5、触发频率
触发器内定义的动作被执行的次数,包括语句级和行级ji。
- 限制
1、触发器不接受参数
2、一个表上最多可有12个触发器,但同一时间、同一事件、同一类型的触发器只能有一个。并各触发器之间不能有矛盾。
3、一个表上的触发器越多,该表上的DM操作的性能影响就越大
4、触发器代码的大小不能超过32K。如需要大量的代码创建触发器,则首先创建过程,然后在触发器中使用CALL语句调用过程
5、触发器代码只能包含SELECT、INSERT、UPDATE和DELETE语句,
6、不能包含DDL语句(CREATE、ALTER和DROP) 和事务控制语句(COMMIT、ROLLBACK和SAVEPOINT)
- 创建dml触发器
语句触发器
1、语句触发器是指当执行DML语句时被隐含执行的触发器
2、如果在表上针对某种DML操作创建了语句触发器,则当执行DML操作时会自动地执行触发器的相应代码
3、为了审计DML操作,或者确保DML操作安全执行时,可以使用语句触发器
触发器用途很多,例如用户清算购物车后将会触发待收货的数据库
代码示例:
--创建触发器
create or replace trigger tri_test
before--触发之前
update or delete--更新或删除
on emp for each row--对行进行操作 begin dbms_output.put_line(:old.sal);--old表示数据库旧值 insert into demo(id) values (:new.sal);--new新值 end; update emp set sal=888 where empno=7788; commit; --代码解释:先执行创建触发器代码后,再执行最后的更新语句。当更新恩平、表后将会输出数据库中本来存放的值,并且触发添加语句在demo表中插入一条语句。
自定义异常,触发器 拦截
简单代码示例1:
-- 触发器 拦截
create or replace trigger tri_test
before
update or delete
on emp for each row begin if to_char(sysdate,'yyyy-mm-dd')='2018-03-13' then--将系统日期转化为字符类型 -- 自定义异常, raise_application_error(-20000,'今天不能修改数据');-- 负20000之前的异常都已经被定义 end if; end; update emp set sal=777 where empno=7788; commit; --触发器创建后,执行最后代码,将会有异常提示:今天不能修改数据
示例2:
create or replace trigger tri_test
before
update or delete or insert
on emp for each row begin case when updating then raise_application_error(-20000,'今天不能修改'); when inserting then raise_application_error(-20001,'今天不能插入'); when deleting then raise_application_error(-20000,'今天不能删除'); end case; end; update emp set sal=777 where empno=7788; insert into emp (empno) values (123); commit;
- 创建替代(instead of)触发器
一般语法:
create or peplace trigger 触发器名称
instead of
操作条件on视图名称
for each row(因为instead of 触发器只能在行级上出发,所以没有必要指定)
begin
操作条件from 表名where 列名= :old.列名;
end;
其中:
instead of 选项使oracle 激活触发器,而不是执行触发器。只能对视图和对象视图建立 instead of触发器,而不能对表、模式和数据库建立instead of 触发器。
总结创建替代触发器的过程:
- 为用户授权
- 创建视图
- 创建触发器
- 执行条件
简答代码示例:
------ 替换触发器创建过程示例 -- 授权 grant create view to scott; -- 创建视图 create view emp_view as select deptno,count(*) total,sum(sal) total_salary from emp group by deptno; --创建触发器 create trigger emp_view_delete instead of delete on emp_view for each row begin delete from emp where deptno= :old.deptno; end; --执行条件 delete from emp_view where deptno=10; select * from emp; rollback;
上述代码中最后 rollback的意思为回滚,和commit用法相反,当不确定要删除数据库中的数据时使用rollback意味着撤回,用commit执行dml语句后,数据库将做出永久改变。
总结替代触发器创建特点:
- 只能被创建在视图上,并且该视图没有指定的with check option选项
- 不能被指定before和after选项
- for each row语句是可选的
- 没有必要针对一个表的视图上创建替代触发器,只要创建dml触发器就可以了
案例
使用触发器实现自动编号
对于表中id自动递增在sql语句中可以用序列来实现,下面是用触发器来实现自动编号;
思路:
- 创建表
- 创建序列
- 创建触发器
- 执行条件
代码如下:
--使用触发器实现自动编号 --创建序列 create sequence stu_seq start with 1 increment by 1 --创建触发器 create or replace trigger tri_stu before insert on student for each row begin select stu_seq.nextval into :new.id from dual; end; --执行条件 insert into student (id,name) values(1,'lwx'); commit;