(2.13)Mysql之SQL基础——触发器
(2.13)Mysql之SQL基础——触发器
关键词:Mysql触发器
【1】触发器
MySQL语句在需要时被执行,存储过程也是如此,如果希望某条语句(或某些语句)在事件发生时自动执行,这就需要用到触发器。
触发器是MySQL响应以下任意语句而自动执行的一条MySQL语句(或位于begin和end语句之间的一组语句):
delete;
insert;
update;
其他MySQL语句不支持触发器。。。
【1.0】创建触发器
需要以下4条信息:
①唯一的触发器名;
②触发器关联的表;
③触发器应该响应的活动(delete、insert或update);
④触发器何时执行(处理之前或之后);
CREATE TRIGGER trigger_name trigger_time trigger_event ON tb_name FOR EACH ROW trigger_stmt
trigger_name:触发器的名称
tirgger_time:触发时机,为BEFORE或者AFTER
trigger_event:触发事件,为INSERT、DELETE或者UPDATE
tb_name:表示建立触发器的表明,就是在哪张表上建立触发器
trigger_stmt:触发器的程序体,可以是一条SQL语句或者是用BEGIN和END包含的多条语句
所以可以说MySQL创建以下六种触发器:
BEFORE INSERT,BEFORE DELETE,BEFORE UPDATE
AFTER INSERT,AFTER DELETE,AFTER UPDATE
PS:MySQL中,触发器名必须在每个表中唯一,但不限制每个数据库中唯一,即:同一数据库中两个表可以具有相同名字的触发器(其他的DBMS中不被允许)。
触发器使用create teigger语句创建,下面是一个简单的例子:
create trigger newproduct after insert on products
for each row select 'product added';
这里创建了一个newproduct的新触发器,给出了after insert,所以此触发器在insert语句成功执行后执行;其中还指定了for each row,因此代码对每个插入行执行。
PS:只有表才支持触发器,视图不支持(临时表也不支持)。
触发器按每个表每个事件每次的定义,每个表每个事件每次只允许一个触发器;因此每个表最多支持6个触发器(每条insert、update和delete的之前和之后),单一触发器不能与多个事件或多个表关联。
如果before触发器失败,则MySQL将不执行请求的操作;此外,如果before触发器或语句本身失败,MySQL将不执行after触发器(如果有的话)。
【1.1】触发器的触发条件
【1.2】删除触发器
删除触发器使用drop trigger语句,例如:
drop trigger newproduct;
PS:触发器不能更新或覆盖;为了修改一个触发器,必须先删后建。
【2】使用触发器
【2.1】new和old的使用
【2.2】一般形式
-- 0.查看触发器
【1】SHOW TRIGGERS;
【2】SELECT * FROM `information_schema`.`TRIGGERS` WHERE `TRIGGER_NAME`='trg_bm_history'; -- 1.一般形式
create trigger trigger_name trigger_time
trigger_event on table_name
for each row
begin
trigger_statement;
end 解析:
(1)trigger_time:触发时间,取值[before/after]即事件发生之前/之后
(2)trigger_event:触发时间,取值[insert/update/delete]即进行增/删/改事件触发该触发器;
(注意replace以及load data等同于Insert事件)
(3)for each row:关键字,对每一行进行触发;以行为单位;
(4)trigger_statement:触发执行语句
(5)old / new 关键字:可以获取到操作之前、操作之后的行数据,一般old用于after时刻,new多用于before时刻
【1】insert操作:一般只使用new,new为新插入的行的数据
【2】update操作:一般使用new和old,new为更新后的数据行,old为更新前的数据行
【3】delete操作:一般只用old,表示删除前的数据行 -- 2.简单案例
#删除表之前使用触发器把被删除的表插入到历史表备份
delimiter //
create trigger trg_bm_history after
delete on bm
for each row
begin
insert into bm_history values(old.b_id,old.b_name);
end //
delimiter ; -- 3.删除
drop trigger trigger_name; -- 4.注意事项
【1】对于相同的表,相同的事件只能创建一个触发器,比如对表 bm 创建了after delete 触发器,就不能再对该表创建 after delete 触发器了;
【2.3】insert触发器
使用insert触发器,需要知道以下三点:
①在insert触发器代码内,可引用一个名为new的虚拟表,访问被插入的行;
②在before insert触发器内,new中的值也可以被更新(允许更改被插入的值);
③对于auto increment列,new在insert执行之前包含0,在insert执行之后包含新的自动生成值;
例子如下:
create trigger neworder before insert on orders
for each row
begin
set new.order_num=1; -- 修改将要插入插入的新行所在 order_num列值为1,插入进去的值就是1了。
end
此代码创建一个名为neworder的触发器,按照after insert on order执行;在插入一条新的数据orders表时,MySQL生成一个新订单号并保存到order_num中;
触发器从new.order_num取这个值并返回它;此触发器必须按照after insert执行,因为在before insert语句执行之前,新order_num还没生成。
PS:通常将before用于数据验证和净化(目的是保证插入表中的数据确实是需要的数据)。这个规则也适用于update触发器。
【2.4】delete触发器
使用delete触发器,需要知道以下两点:
①在delete触发器代码内,可以引用一个名为old的虚拟表,访问被删除的行;
②old中的值全都是只读的,不能更新;
下面是一个使用old保存将要被删除的行到一个存档表中:
create trigger deleteorder before delete on orders
for each row
begin
insert into archive_orders(order_num,order_date,cust_id)
values(OLD_order_num, OLD_order_date, OLD_cust_id);
end;
此代码在任意orders表中的数据被删除前执行此触发器;它使用一条insert语句将old中的值(要被删除的数据)保存到一个名为archive_orders的存档表中;
上面的例子中,使用begin end块的好处是触发器能容纳多条SQL语句。
PS:使用before delete触发器的优点:如果由于某些原因,数据不能存档,delete本身将被放弃。
【2.5】update触发器
使用update触发器,需要知道以下三点:
①在update触发器代码内,可以引用一个名为old的虚拟表访问以前(update语句前)的值,引用一个名为new的虚拟表访问新更新的值;
②在before update触发器中,new中的值可能也被更新(允许更改将要用于update语句中的值);
③old中的值全都是只读的,不能更新;
下面的例子,保证了州名称缩写总是大写:
create trigger updateevendor before update on vendors
for each row set.vend_state = upper(new.vend_state);
这个例子中,每次更新一个行时,new.vend_state中的值(将用来更新表行的值)都用upper(new.vend_state)替换。
△关于触发器一些必须知道的知识:
①创建触发器可能需要特殊的安全访问权限,但触发器的执行是自动的;如果insert、update、delete语句可以执行,则相应触发器也能执行;
②应该用触发器来保证数据的一致性(大小写、格式等);有点在于它总是进行这种处理,而且是透明的进行,与客户机应用无关;
③触发器的一种非常有意义的使用是创建审计跟踪。使用触发器,把更改记录到另一个表非常容易;
④MySQL触发器不支持call语句,即不能从触发器内调用存储过程,所需的存储过程代码需要复制到触发器内。
案例:插入数据前,记下当条记录的其插入id+1;
delimiter //
create trigger trg_bm_max before
insert on bm
for each row
begin
update dm_count set count_max=new.b_id+1;
end //
delimiter ;
【3】最佳实践
【3.1】当表新增行后,修改该表新增行中的某个字段值
delimiter //
create trigger trg_update_prefix_app before
insert on prefix_app
for each row
begin
set new.in_icon=replace(new.in_icon,'oss-cn-zhangjiakou-internal.aliyuncs.com','firzjk.oss-cn-zhangjiakou.aliyuncs.com');
end //
delimiter ;
参考:https://www.cnblogs.com/zh-1721342390/p/9602941.html
(2.13)Mysql之SQL基础——触发器的更多相关文章
- (2.16)Mysql之SQL基础——函数
(2.16)Mysql之SQL基础——函数 关键词:mysql函数,mysql自定义函数,mysql聚合函数,mysql字符串函数,mysql数值函数 1.自定义函数 -- (1)一般形式 creat ...
- (2.15)Mysql之SQL基础——开发设计最佳规范
(2.15)Mysql之SQL基础——开发设计最佳规范 关键字:mysql三大范式,mysql sql开发规范 分析: show profile.mysqllsla.mysqldrmpslow.exp ...
- (2.14)Mysql之SQL基础——游标
(2.14)Mysql之SQL基础——游标 关键词:Mysql游标 -- (1)定义游标 declare cur_name cursor for select * from table_name wh ...
- (2.11)Mysql之SQL基础——存储过程与变量
(2.11)Mysql之SQL基础——存储过程 关键字:mysql存储过程 查看存储过程: []SELECT * FROM information_schema.ROUTINES WHERE ROUT ...
- (2.10)Mysql之SQL基础——约束及主键重复处理
(2.10)Mysql之SQL基础——约束及主键重复处理 关键词:mysql约束,批量插入数据主键冲突 [1]查看索引: show index from table_name; [2]查看有约束的列: ...
- (2.9)Mysql之SQL基础——索引的查看与删除
(2.9)Mysql之SQL基础——索引的查看与删除 关键词:mysql索引查看,mysql索引删除 1.索引查询(以下包括主键,唯一,普通,复合,全文,但不包括外键) (1)按库查询 select ...
- (2.8)Mysql之SQL基础——索引的分类与使用
(2.8)Mysql之SQL基础——索引的分类与使用 关键字:mysql索引,mysql增加索引,mysql修改索引,mysql删除索引 按逻辑分类: 1.主键索引(聚集索引)(也是唯一索引,不允许有 ...
- (2.7)Mysql之SQL基础——表的操作与查看
(2.7)Mysql之SQL基础——表的操作与查看 搜索关键字:mysql表操作,comment注释操作,mysql临时表 0.临时表 create temporary table 1.创建表(在in ...
- (2.6)Mysql之SQL基础——存储引擎的查看与修改
(2.6)Mysql之SQL基础——存储引擎的查看与修改 可以使用 show engines; 查看数据库支持的所有的存储引擎: 目录: 1.数据库级别存储引擎 1.1查看现在默认的存储引擎 1.2 ...
随机推荐
- easyUI实现(alert)提示框自动关闭的实例代码
function alert_autoClose(title,msg,icon){ var interval; var time=1000; var x=2; //设置时间2s $.messa ...
- mysql数据库,查看数据存放目录datadir
需求描述: 在使用数据库,或者刚接手一个数据库时,可以查看该数据库的数据文件存放在什么位置. 操作过程: 1.通过查看datadir系统变量来查看数据目录 [mysql@redhat6 mysql-b ...
- 50个Android开发技巧(03 自己定义ViewGroup)
问题:怎样创建一个例如以下图所看到的的布局? 图1 (原文地址:http://blog.csdn.net/vector_yi/article/details/244155 ...
- K - problem 问题
Leetcode 有几个题目, 分别是 2sum, 3sum(closest), 4sum 的求和问题和 single Number I II, 这些题目难点在于用最低的时间复杂度找到结果 2-sum ...
- 《C++ Primer Plus》15.1 友元 学习笔记
15.1.1 友元类假定需要编写一个模拟电视机和遥控器的简单程序.决定定义一个Tv类和一个Remote类,来分别表示电视机和遥控器.遥控器和电视机之间既不是is-a关系也不是has-a关系.事实上,遥 ...
- ubuntu下code::blocks编译运行一个简单的gtk+2.0项目
在具体的操作之前,首先需要安装一些必要的软件.ubuntu下默认安装了gcc,不过缺少必要的Header file,可以在命令行中输入下面的指令安装build-essential套件:sudo apt ...
- PyQt4关闭窗口
一个显而易见的关闭窗口的方式是但集标题兰有上角的X标记.接下来的示例展示如何用代码来关闭程序,并简要介绍Qt的信号和槽机制. 下面是QPushButton的构造函数,我们将会在下面的示例中使用它. Q ...
- Tomcat7.0无法启动解决方法[failed to start]
很奇怪的一个问题,Tomcat一直好好的,运行Servlet之后就报这个错: 为什么呢?在网上查都查不到解决方法,后来仔细检查了下Servlet,发现web.xml有个低级错误: 配置的Servlet ...
- MACOS配置VIM成简单IDE傻瓜式操作
零.参考文献: https://www.jianshu.com/p/f0513d18742a 一.安照我的配置:保存文件 " Configuration file for vim " ...
- Minix2.0操作系统公用头文件说明
以下头文件均在目录include/下: ansi.h: 用来检测编译器是否遵循标准C,如果是的话,_ANSI就被定义为31415,如果不是的,则_ANSI未定义.通过这个宏来诊测. limits.h: ...