触发器

  • 触发器组成

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 触发器。

总结创建替代触发器的过程:

  1. 为用户授权
  2. 创建视图
  3. 创建触发器
  4. 执行条件

简答代码示例:

复制代码
------  替换触发器创建过程示例

-- 授权
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语句后,数据库将做出永久改变。

总结替代触发器创建特点:

  1. 只能被创建在视图上,并且该视图没有指定的with check option选项
  2. 不能被指定before和after选项
  3. for each row语句是可选的
  4. 没有必要针对一个表的视图上创建替代触发器,只要创建dml触发器就可以了

案例

使用触发器实现自动编号

对于表中id自动递增在sql语句中可以用序列来实现,下面是用触发器来实现自动编号;

思路:

  1. 创建表
  2. 创建序列
  3. 创建触发器
  4. 执行条件

代码如下:

复制代码
--使用触发器实现自动编号
--创建序列
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;
 
 
posted on 2023-01-12 15:32  旧路人  阅读(94)  评论(0编辑  收藏  举报