oracle 进阶(五)触发器的使用
触发器
触发器是一种特殊类型的过程。
与普通过程不同的是,过程需要用户显式地调用才执行,
而触发器则是当某些事件发生时,由 Oracle 自动执行,也就是隐式执行的。
1、触发器的组成
触发器主要由如下几个部分组成:
触发事件: 引起触发器被触发的事件。
如 DML 语句(如 INSERT、UPDATE、DELETE)、DDL 语句(如 CREATE、ALTER、DROP)、
数据库系统事件(如系统启动或退出、异常错误)、用户事件(如登录或退出数据库)等。
触发时机:指定触发器的触发时间。
BEFORE 表示在执行 DML 操作之前触发;
AFTER 表示在执行 DML 操作之后触发。
触发类型:指定触发事件发生后需要执行几次触发器。
即,是语句级触发器(默认)还是行级触发器。
触发对象:包括表、视图、模式、数据库。
触发条件:由 WHEN 子句指定的是一个逻辑表达式。
只有当该表达式的值为 TRUE 时,遇到触发事件才会自动执行触发器,否则即便遇到触发事件也不会执行触发器。
2、触发器类型
3、创建触发器的语法
行级和语句级触发器语法:
CREATE [OR REPLACE] TRIGGER trigger_name
{BEFORE | AFTER }
{INSERT | DELETE | UPDATE [OF column [, column …]]}
[OR {INSERT | DELETE | UPDATE [OF column [, column …]]}...]
ON [schema.]table_name | [schema.]view_name
[REFERENCING {OLD [AS] old | NEW [AS] new| PARENT as parent}]
[FOR EACH ROW ]
[WHEN condition]
PL/SQL_BLOCK | CALL procedure_name;
INSTEAD OF 触发器语法:
CREATE [OR REPLACE] TRIGGER trigger_name
INSTEAD OF
{INSERT | DELETE | UPDATE [OF column [, column …]]}
[OR {INSERT | DELETE | UPDATE [OF column [, column …]]}...]
ON [schema.] view_name --只能定义在视图上
[REFERENCING {OLD [AS] old | NEW [AS] new| PARENT as parent}]
[FOR EACH ROW ] --因为INSTEAD OF触发器只能在行级上触发,所以没有必要指定
[WHEN condition]
PL/SQL_block | CALL procedure_name;
系统事件触发器语法
CREATE OR REPLACE TRIGGER [sachema.]trigger_name
{BEFORE|AFTER}
{ddl_event_list | database_event_list}
ON { DATABASE | [schema.]SCHEMA }
[WHEN condition]
PL/SQL_block | CALL procedure_name;
说明:
其中: ddl_event_list:一个或多个 DDL 事件,事件间用 OR 分开;
database_event_list:一个或多个数据库事件,事件间用 OR 分开;
系统事件触发器既可以建立在一个模式上,又可以建立在整个数据库上。当建立在模式 (SCHEMA) 之上时,只有模式所指定用户的 DDL 操作和它们所导致的错误才激活触发器, 默认时为当前用户模式。当建立在数据库 (DATABASE) 之上时,该数据库所有用户的 DDL 操作和他们所导致的错误,以及数据库的启动和关闭均可激活触发器。要在数据库之上建立触发器时,要求用户具有 ADMINISTER DATABASE TRIGGER 权限。
下面给出系统触发器的种类和事件出现的时机(前或后):
事件 | 允许的时机 | 说明 |
STARTUP | AFTER | 启动数据库实例之后触发 |
SHUTDOWN | BEFORE | 关闭数据库实例之前触发(非正常关闭不触发) |
SERVERERROR | AFTER | 数据库服务器发生错误之后触发 |
LOGON | AFTER | 成功登录连接到数据库后触发 |
LOGOFF | BEFORE | 开始断开数据库连接之前触发 |
CREATE | BEFORE,AFTER | 在执行 CREATE 语句创建数据库对象之前、之后触发 |
DROP | BEFORE,AFTER | 在执行 DROP 语句删除数据库对象之前、之后触发 |
ALTER | BEFORE,AFTER | 在执行 ALTER 语句更新数据库对象之前、之后触发 |
DDL | BEFORE,AFTER | 在执行大多数 DDL 语句之前、之后触发 |
GRANT | BEFORE,AFTER | 执行 GRANT 语句授予权限之前、之后触发 |
REVOKE | BEFORE,AFTER | 执行 REVOKE 语句收权限之前、之后触犯发 |
RENAME | BEFORE,AFTER | 执行 RENAME 语句更改数据库对象名称之前、之后触犯发 |
AUDIT / NOAUDIT | BEFORE,AFTER | 执行 AUDIT 或 NOAUDIT 进行审计或停止审计之前、之后触发 |
4、示例
语句级触发器示例:
create or replace trigger tig_dept_time
before insert or update or delete
on DEPT
begin
if( to_char(sysdate,'day') in ('星期六','星期日') or
sysdate not between to_date(to_char(sysdate,'yyyyMMdd')||'08:30:00','yyyyMMdd HH24:MI:SS')
and to_date(to_char(sysdate,'yyyyMMdd')||'18:00:00','yyyyMMdd HH24:MI:SS' ) )
then
raise_application_error(-20001,'不是上班时间,不允许修改dept表');
end if;
end;
行级触发器
--创建行级触发器
create or replace trigger tig_salary_raiu
--触发时机
after
--触发类型,可以有多个,多个用or隔开如insert or update,只有当amount列被更新时,update才会被触发
insert or update of amount
--触发对象
on salary
for each row
begin
if inserting then
dbms_output.put_line('插入');
elsif updating then
dbms_output.put_line('更新');
end if;
end;
Instead of 类型触发器
--创建视图
CREATE OR REPLACE VIEW emp_view AS
SELECT deptno, count(*) total_employeer, sum(sal) total_salary
FROM emp GROUP BY deptno;
--创建Instead of触发器
CREATE OR REPLACE TRIGGER emp_view_delete
INSTEAD OF DELETE ON emp_view FOR EACH ROW
BEGIN
DELETE FROM emp WHERE deptno= :old.deptno;
END ;
系统事件触发器
--创建记录表
CREATE TABLE log_event
(user_name VARCHAR2(10),
address VARCHAR2(20),
logon_date date,
logoff_date date);
--创建登录触发器
CREATE OR REPLACE TRIGGER tig_logon
AFTER LOGON ON DATABASE
BEGIN
INSERT INTO log_event (user_name, address, logon_date)
VALUES (ora_login_user, ora_client_ip_address, sysdate);
END tig_logon;
--创建退出触发器
CREATE OR REPLACE TRIGGER tig_logoff
BEFORE LOGOFF ON DATABASE
BEGIN
INSERT INTO log_event (user_name, address, logoff_date)
VALUES (ora_login_user, ora_client_ip_address, sysdate);
END tig_logoff;
5、禁用和启用触发器
数据库 TRIGGER 的状态:
有效状态 (ENABLE):当触发事件发生时,处于有效状态的数据库触发器 TRIGGER 将被触发。
无效状态 (DISABLE):当触发事件发生时,处于无效状态的数据库触发器 TRIGGER 将不会被触发,此时就跟没有这个数据库触发器 (TRIGGER) 一样。
数据库 TRIGGER 的这两种状态可以互相转换。格式为:
ALTER TIGGER trigger_name [DISABLE | ENABLE ];
ALTER TABLE [schema.]table_name {ENABLE|DISABLE} ALL TRIGGERS;
说明:
ALTER TRIGGER 语句一次只能改变一个触发器的状态,针对触发器本身做出禁用和可用处理,同时针对该触发器在表上是否允许可用做出处理;而 ALTER TABLE 语句则一次能够改变与指定表相关的所有触发器的使用状态,只针对触发器在表上是否允许可用做出处理。
例如:
ALTER TIGGER tig_logon DISABLE;
ALTER TIGGER tig_logon ENABLE;
ALTER TABLE emp DISABLE ALL TRIGGERS;
ALTER TABLE emp ENABLE ALL TRIGGERS;
6、删除触发器
语法
DROP TRIGGER trigger_name;
说明:
当删除其他用户模式中的触发器名称,需要具有 DROP ANY TRIGGER 系统权限,当删除建立在数据库上的触发器时,用户需要具有 ADMINISTER DATABASE TRIGGER 系统权限。此外,当删除表或视图时,建立在这些对象上的触发器也随之删除。
例如:
DROP TRIGGER tig_logoff;