触发器的一般语法结构:
create [or replace] trigger Ttrigger_name {before|after} Triggering_event on table_name [for each row] [follows another_trigger] [enable/disable] [when condition] declare declaration statemebts begin executable statements exception exception-handling sttements end;
解析:
create [or replace] trigger: 表示将创建或者替换一个触发器,如果没有写or replace则只会创建一个触发器,当数据库中已经有该触发器了,则新创建不会成功。
Ttrigger_name:触发器的名字
{before|after} Triggering_event on table_name:表示在table_name表上创建的触发器事件发生的前或者后,触发器会触发
Triggering_event:比如插入或者更新等操作,也可能是时间
[for each row]:表示行级触发器,是对每一行数据都会触发判断。若没有这一句,则是语句级触发器,一次触发只会执行一次
[enable/disable]:是触发器启用或禁用选项,默认是启用的,禁用触发器的例句:after trigger trigger_anme disable
follows :可以指定触发器的顺序
declare:后面是申明部分
beigin...end:中间是主体语句
exception后面抛出异常
a、删除一个表,表上的触发器也会一起被删除
触发器的一些作用:
a、执行不能通过使用完整性约束来定义的复杂业务规则
b、维护复杂的安全规则
c、自动生成衍生列的值
d、收集有关访问数据库表的统计信息
e、防止无效的事务
f、提供值审计
触发器不会执行事务控制语句,比如commit和rollback等,当触发器执行时,执行commit和rollback时,触发器也会被提交或者回滚
例句:
1:
CREATE OR REPLACE TRIGGER forbid_emp_trigger BEFORE INSERT OR DELETE OR UPDATE ON emp DECLARE v_currentweak VARCHAR(20); v_currenthour VARCHAR(20); BEGIN SELECT TO_CHAR(SYSDATE,'day'),TO_CHAR(SYSDATE,'hh24') INTO v_currentweak, v_currenthour FROM dual ; IF TRIM(v_currentweak)='星期一' OR TRIM(v_currentweak)='星期六' OR TRIM(v_currentweak)='星期日' THEN RAISE_APPLICATION_ERROR(-20008,'在周末及周一不允许更新emp数据表!') ; ELSIF TRIM(v_currenthour)<'9' OR TRIM(v_currenthour)>'18' THEN RAISE_APPLICATION_ERROR(-20009,'在下班时间不能够修改emp表数据!') ; END IF; END;
会判断当前日期,如果在周一、周末或者下班时间,不允许插入,删除,更新数据库数据
2:
create or replace trigger tri_no_gzjiang before update on emp declare var_data varchar2(20); begin select to_char(sysdate,'hh24') into var_date from dual; if var_date > '12' then raise_application_error(-20009,'12点之后不能够修改emp表数据!'); end if; end;
3:
create or replace trigger CASCADE_DEL_UPD before update of deptno or delete on dept for each row declare begin if deleting then delete from emp where deptno=:old.deptno; end if; if updating then update emp set deptno=:new.deptno where deptno=:old.deptno; end if; end;
4:
--创建一个视图 create or replace view view_emp_dept as select empno,ename,dept.deptno,dname,job,hiredate from emp ,dept where emp.deptno = dept.deptno; --插入记录 insert into view_emp_dept(empno,ename,deptno,dname,job,hiredate) values (999,'ttgg',10,'ACCOUNTING','CASHIER',sysdate); --插入数据失败,通过关联触发器来 --创建触发器 create or replace trigger tri_insert_view instead of insert on view_emp_dept for each row declare row_dept dept%rowtype; begin select * into row_dept from dept where deptno=:new.deptno; if sql%notfound then insert into dept(deptno,dname) values(:new.deptno,:new.dname); end if; insert into emp(empno,ename,deptno,job,hiredate) values (:new.empno,:new.ename,:new.deptno,:new.job,:new.hiredate); end; --验证触发器 insert into view_emp_dept(empno,ename,deptno,dname,job,hiredate) values (999,'ttgg',10,'ACCOUNTING','CASHIER',sysdate); select * from view_emp_dept;