15)触发器
Posted xuan01
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了15)触发器相关的知识,希望对你有一定的参考价值。
1、触发事件:
触发器定义了一系列操作,称为触发程序,当触发事件发生时,触发程序会自动运行;格式如下:
create trigger 触发器名 触发时间 触发事件 on 表名 for each row begin 触发程序 end;
触发时间:before、after;
触发事件:insert、update、delete;
for each now:表示行级触发器;
2、使用触发器实现检查约束:
使用触发器实现检查约束,确保课程的人数上限 up_limit 字段值在(60,150,230)范围内;
delimiter $$ create trigger insert_before_course_trigger before insert on course for each row begin if new.up_limit not in(60,150,230) then signal sqlstate \'ERROR\' set message_text = \'选修人数上限只能在60、150、230之间取值\'; #引发错误方式 end if; end; $$ delimiter ;
new获取新值的标识符;old获取原值的标识符;使用格式:
new.字段 或 old.字段
signal sqlstate 为引发错误的方式;
执行下列测试语句;
insert into course values(null,\'音乐鉴赏\',100,\'暂无\',default,\'005\');
发现会报错;而且正是我们在signal那行所设定的 message_text 的值;原因在于我们设定的触发器就是让 up_limit 的值只能三选一;不能自定;
执行下列测试语句:
insert into course values(null,\'音乐鉴赏\',150,\'暂无\',default,\'005\');
发现可以成功插入;
到此,我们执行update语句结果会怎么样呢?执行下列测试语句:我们更新course_no= 5 的up_limit的值:
update course set up_limit=100 where course_no = 5;
发现成功update,这与我们设定的up_limit 的值不符合;那么我们如何修正呢?
那就是我们设定一个 update 的触发器;我们让其变更为原值;
delimiter $$ create trigger update_before_course_trigger before update on course for each row begin if new.up_limit not in(60,150,230) then set new.up_limit = old.up_limit; end if; end; $$ delimiter ;
那么我们将执行下列测试语句,修改为符合值;
update course set up_limit=150 where course_no = 5;
可以发现我们可以修改为符合的值;再测试一下我们将其更新为不符合的值:
update course set up_limit=100 where course_no = 5;
可以看到虽然我们匹配找到了一行,但是changed为0,就是未作update操作;
至此,我们的insert触发器和update触发器就完成了,维持 up_limit 的值只能在三选一;
我们可以再测试一下,当我们同时修改其他字段时:
update course set up_limit=100, status=\'已审核\' where course_no = 5;
可以发现,我们的up_limit 字段未作修改,但是status更新为已审核了,因为我们没有对该字段进行约束,符合预期;
3、查看和删除触发器:
#查看所有触发器
show triggers\\G
#查看指定触发器名 show create trigger 触发器名\\G
show create trigger insert_before_course_trigger\\G
貌似MySQL8.0版本之后不支持下列模糊查看了:
show trigger like \'%trigger\'\\G
通过查询GPT,可以使用以下方法:
select * from information_schema.triggers where trigger_name like \'%\\_trigger\'\\G
查询information_schema下的triggers表,通过匹配名字进行模糊查找;
删除触发器命令:
#删除触发器 drop trigger 触发器;
触发器
本节要点:
- 什么是触发器
- 触发器类型及创建方法
- 触发器类型
- 创建触发器
- 触发器组成部分
- 理解和应用触发器
- 行级触发器
- 语句级触发器
- INSTEAD OF 触发器
- 模式触发器
- 启用、禁用和删除触发器
1 什么是触发器
触发器和存储过程比较类似,它由PL/SQL编写并存储在数据库中,它可以调用存储过程,但是触发器本身的调用和存储过程调用是不一样的。存储过程由用户、应用程序、触发器或者其他过程调用。但是触发器只能由数据库的特定事件来触发。所以,触发器是当特定事件出现时自动执行的存储过程,不能被显式调用,特定事件可以是执行更新的DML语句和DDL语句。
触发器的作用:
- l 自动生成数据:如序列
- l 自定义复杂的安全权限:比如可以实现完整性规则
- l 提供审计和日志记录
- l 启用复杂的业务逻辑:除了基础数据变动还可以完成一些额外的操作
2 触发器类型及创建方法
触发器类型主要有DDL 触发器、数据库级触发器和DML触发器,其中DML触发器又可以分为语句级触发器、行级触发器和INSTEAD OF 触发器等。
2.1 触发器类型
- DDL 触发器:在模式中执行 DDL 语句时执行
- 数据库级触发器:在发生打开、关闭、登录和退出数据库等系统事件时执行
- DML 触发器:在对表或视图执行DML语句时执行
- 语句级触发器:无论受影响的行数是多少,都只执行一次
- 行级触发器:对DML语句修改的每个行执行一次
- INSTEAD OF 触发器:用于用户不能直接使用 DML 语句修改的视图
2.2 创建触发器
语法:
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;
- TRIGGER:触发器的关键词
- AFTER | BEFORE | INSTEAD OF:触发器类型为前触发|后触发|替换类型
- INSERT| UPDATE| DELETE:表示触发的事件
- [OF column_list]:触发条件具体到的某列
- ON table_or_view_name:触发器作用的表或视图
- [FOR EACH ROW]:表示行级触发,省略则为语句级触发器
- [WHEN (condition)]:触发该触发器的条件
- pl/sql_block:表示触发器的函数体
示例:为表m_user的user_pswd字段创建更新前触发的触发器,OLD.表示访问前的数据,:NEW.表示访问后的数据
CREATE OR REPLACE TRIGGER trig_stu
BEFORE UPDATE OF user_pswd ON m_user
FOR EACH ROW
WHEN (OLD.user_nm = ‘3‘)
BEGIN
:NEW.user_nm := ‘333333‘;
END;
更新语句
update m_user t set t.user_pswd=‘555‘ where t.user_cd=‘7‘;
2.3 触发器的组成部分
触发器由三部分组成:
1) 触发器语句(事件):定义激活触发器的 DML 事件和 DDL 事件
示例:为m_user表创建trig_stu触发器
CREATE OR REPLACE TRIGGER trig_stu
在更新 user_pswd列之前激活触发器
BEFORE UPDATE OF user_pswd ON m_user
2) 触发器限制:执行触发器的条件,该条件必须为真才能激活触发器,即WHEN (condition)部分
示例:只有在WHEN子句中的条件得到满足时,才激活trig_stu触发器
WHEN (OLD.user_nm = ‘3‘)
3) 触发器操作(主体):包含一些 SQL 语句和代码,它们在发出了触发器语句且触发限制的值为真时运行,即pl/sql_block部分
示例:如果WHEN子句中的条件得到满足,将执行BEGIN 块中的代码
:NEW.user_nm := ‘333333‘;
3 理解和应用触发器
3.1 行级触发器
创建表:
create table t_temp(f_id number,f_name varchar2(20));
创建序列:
create sequence seq_tempid;
创建触发器:
create trigger trig_temp
/*表t_temp更新或者插入字段f_id时触发器被触发*/
before insert or update of f_id on t_temp
for each row
begin
/*如果事件“inserting”发生,则执行1号语句,否则执行2号语句,注:不包括更新*/
if inserting then
select seq_tempid.nextval into :New.f_id from dual;/*1号*/
else
Raise_Application_Error(-20020, ‘不允许更新ID值!‘);/*2号*/
end if;
end;
插入数据(正常):
insert into t_temp (f_id,f_name) values(‘11‘,‘name1‘);
更新数据(报错):
update t_temp set f_id=‘11‘ where f_id=‘1‘;
删掉触发器:
drop trigger trig_temp;
再次更新数据(正常)。
说明:触发器的功能起作用。
3.2 语句级触发
create or replace trigger trig_stu
after insert or delete or update
on t_student
begin
if inserting then
dbms_output.put_line(‘已添加t_student中的数据‘);
elsif deleting then
dbms_output.put_line(‘已删除t_student中的数据‘);
elsif updating then
dbms_output.put_line(‘已更新t_student中的数据‘);
end if;
end;
注:没有for each row,根据语句的类型来触发相应的操作。
3.3 INSTEAD OF 触发器
在该类型的触发器作用下,如果对作用对象执行DML操作,那么该操作会被触发器的内部操作所取代。可以用在视图当中,解决视图不可更新的问题。
示例:对视图进行数据插入时,实际是操作其依附的真正存在的表productinfo,而productinfo表中产品类型信息是与表categroyinfo关联的,无法对视图直接进行数据插入。所以有了INSTEAD OF 触发器,在插入数据之前根据category查询出类型的编号categid,再进行数据插入。
- 表productinfo有七个字段:productid、productname、productprice、quantity、category、desperation、origin。
- 表categroyinfo保存了产品类型信息categroyid 和category
- 视图productinfo_view的定义
create view productinfo_view as
select distinct productname, productprice, quantity, category, origin
from productinfo
- 创建触发器
Create trigger instead_of_tgr
Instead of insert on productinfo_view
Declare
Categid varchar2(10);
Begin
Select categroyid
Into categid
From categroyinfo
Where categroyinfo.categroyname = :new.category;
Insert into productinfo
Values
(‘0240090001’,
:new. Productname,
:new. productprice,
:new. quantity,
Categid,
‘test’,
:new. Origin);
End;
- 对视图进行增加操作,最后productinfo中的category字段将对应categroyinfo中categroyid的编号。
Insert into productinfo_view values(‘触发器测试’,1000,0,’雨具’,’中国’);
3.4 模式触发器
也称DDL类型触发器,即因DDL操作而激发的触发器。利用模式触发器可以限制和记录特定的DDL操作。
示例:创建一个表和模式触发器,通过触发器将删除表的日志记录到表中
创建日志表:create table t_droppedobj
(
f_objname varchar2(20),
f_objtype varchar2(20),
f_dropdate date
);
创建触发器:create or replace trigger trig_dropobj
after drop on schema
begin
insert into t_droppedobj values
(Ora_Dict_Obj_Name,Ora_Dict_Obj_Type,Sysdate);
end;
3.5 启用、禁用和删除触发器
1) 启用触发器
ALTER TRIGGER trig_stu ENABLE;
2) 禁用触发器
ALTER TRIGGER trig_stu DISABLE;
3) 删除触发器
DROP TRIGGER trig_stu;
4) 查看有关触发器的信息:USER_TRIGGERS 数据字典视图包含有关触发器的信息
根据表名称查询触发器信息:
SELECT TRIGGER_NAME FROM USER_TRIGGERS
WHERE TABLE_NAME=‘M_USER ‘; /*注意表名称要大写*/
根据触发器名称查询触发器信息:
SELECT TRIGGER_TYPE, TRIGGERING_EVENT, WHEN_CLAUSE
FROM USER_TRIGGERS
WHERE TRIGGER_NAME = ‘TRIG_TEMP ‘;
以上是关于15)触发器的主要内容,如果未能解决你的问题,请参考以下文章