-
mysql的随机IO,顺序IO,主键与外健的区别,before与after触发器,绑定变量,全文索引
2018-06-06 22:00:41数据备份和日志记录等业务是顺序IO业务。随机IO是指读写操作时间连续,但访问地址不连续,随机分布在磁盘LUN的地址空间中。产生随机IO的业务有OLTP服务,SQL,即时消息服务等。(其实就是说在数据库查询时读取...顺序IO&随机IO
顺序IO是指读取和写入操作基于逻辑块逐个连续访问来自相邻地址的数据。在顺序IO访问中,HDD所需的磁道搜索时间显着减少,因为读/写磁头可以以最小的移动访问下一个块。数据备份和日志记录等业务是顺序IO业务。随机IO是指读写操作时间连续,但访问地址不连续,随机分布在磁盘LUN的地址空间中。产生随机IO的业务有OLTP服务,SQL,即时消息服务等。(其实就是说在数据库查询时读取的不是连续区域,是要在整个磁盘上进行查找,多数时间可能耗费在了磁头寻道上)
① 顺序I/O一般只需扫描一次数据、所以、缓存对它用处不大
② 顺序I/O比随机I/O快
③ 随机I/O通常只要查找特定的行、但I/O的粒度是页级的、其中大部分是寻址,耗费时间,顺序I/O所读取的数据、通常发生在想要的数据块上的所有行更加符合成本效益。 所以、缓存随机I/O可以节省更多的workloadSQL的主键和外键的作用:
外键取值规则:空值或参照的主键值。
(1)插入非空值时,如果主键表中没有这个值,则不能插入。
(2)更新时,不能改为主键表中没有的值。
(3)删除主键表记录时,你可以在建外键时选定外键记录一起级联删除还是拒绝删除。
(4)更新主键记录时,同样有级联更新和拒绝执行的选择。
简而言之,SQL的主键和外键就是起约束作用。
关系型数据库中的一条记录中有若干个属性,若其中某一个属性组(注意是组)能唯一标识一条记录,该属性组就可以成为一个主键。
比如:
学生表(学号,姓名,性别,班级)
其中每个学生的学号是唯一的,学号就是一个主键;
课程表(课程编号,课程名,学分)
其中课程编号是唯一的,课程编号就是一个主键;
成绩表(学号,课程号,成绩)
成绩表中单一一个属性无法唯一标识一条记录,学号和课程号的组合才可以唯一标识一条记录,所以,学号和课程号的属性组是一个主键。
成绩表中的学号不是成绩表的主键,但它和学生表中的学号相对应,并且学生表中的学号是学生表的主键,则称成绩表中的学号是学生表的外键;同理,成绩表中的课程号是课程表的外键。
定义主键和外键主要是为了维护关系数据库的完整性,总结一下:
一、主键是能确定一条记录的唯一标识,比如,一条记录包括身份正号,姓名,年龄。身份证号是唯一能确定你这个人的,其他都可能有重复,所以,身份证号是主键。
外键用于与另一张表的关联。是能确定另一张表记录的字段,用于保持数据的一致性。比如,A表中的一个字段,是B表的主键,那他就可以是A表的外键。
二、主键、外键和索引的区别
定义:
主键--唯一标识一条记录,不能有重复的,不允许为空
外键--表的外键是另一表的主键, 外键可以有重复的, 可以是空值
索引--该字段没有重复值,但可以有一个空值
作用:
主键--用来保证数据完整性
外键--用来和其他表建立联系用的
索引--是提高查询排序的速度
个数:
主键--主键只能有一个
外键--一个表可以有多个外键
索引--一个表可以有多个唯一索引
触发器:
关于触发器可以先读这篇文章:
https://www.cnblogs.com/yank/p/4193820.html
Before与After区别:before:(insert、update)可以对new进行修改。 after不能对new进行修改,两者都不能修改old数据。
after:是先完成数据的增删改,然后再触发,触发的语句晚于监视的增删改,无法影响前面的增删改动作;也就是说先插入订单记录,再更新商品数量。当商品数量少于订单数量时造成爆库。 before:先完成触发,在进行增删改,触发语句先于监视的增删改,我们就有机会判断,修改即将发生的操作。 案例操作: 触发器使用after: 当某个订单的数量超过库存的数量时会出现库存为负数。造成所谓的爆库问题。
触发器,顾名思义,就是当执行某个事件的时候触发另一个事件的执行!这个触发的时间分为BEFORE和AFTER两种,分别有before insert,before update,before delete和after insert,after update,after delete这六种情况
FOR EACH ROW 子句通知触发器每隔一行执行一次动作,而不是对整个表,在触发器中我们经常会用到NEW和OLD这两个关键字,在这里我还是先解释下这两个字的意思!其中NEW是指刚刚插入到数据库的数据表中的一个域,也可以理解为对象(object)的意思。比如在一个insert触发器中我用到了NEW那他的意思就是说,要使用刚刚插入到数据表的某个值,要使用具体的某一个值的话需要这样子写:NEW.字段名(NEW.username)这样子就获取到了刚刚插入到数据表中的一个字段的值!!OLD,OLD是在delete触发器中有用的,意思是说我要删除一条数据,但是在触发器中要用到之前的那个数据,那么我就可以通过OLD来获取了!比如我删除了一条数据,里面包含一个email,现在我在触发器的内部sql中要用就可以这样子写:OLD.email!
对于INSERT语句, 只有NEW是合法的;对于DELETE语句,只有OLD才合法;而UPDATE语句可以在和NEW以及OLD同时使。
触发器的使用案例:http://database.51cto.com/art/201005/200671.htm
绑定变量
绑定变量是为了减少解析的,比如你有个语句这样
select aaa,bbb from ccc where ddd=eee;
如果经常通过改变eee这个谓词赋值来查询,像如下
select aaa,bbb from ccc where ddd=fff; select aaa,bbb from ccc where ddd=ggg; select aaa,bbb from ccc where ddd=hhh;
每条语句都要被数据库解析一次,这样比较浪费资源,如果把eee换成“:1”这样的绑定变量形式,无论ddd后面是什么值,都不需要重复解析。
Java实现绑定变量的方法:
[java] view plaincopy PreparedStatement pstmt = con.prepareStatement("UPDATE employees SET salay = ? WHERE id = ?"); pstmt.setBigDecimal(1, 15.00); pstmt.setInt(2, 110592); /result statmement: UPDATE employees SET salay = 15.00 WHERE id = 110592 pstmt.executeQuery();
假设要将id从1到10000的员工的工资都更新为150.00元,不使用绑定变量,则:
[java] view plaincopy sql.executeQuery("UPDATE employees SET salay = 150.00 WHERE id = 1"); sql.executeQuery("UPDATE employees SET salay = 150.00 WHERE id = 2"); sql.executeQuery("UPDATE employees SET salay = 150.00 WHERE id = 3"); sql.executeQuery("UPDATE employees SET salay = 150.00 WHERE id = 4"); .... sql.executeQuery("UPDATE employees SET salay = 150.00 WHERE id = 10000");
使用绑定变量,则:
[java] view plaincopy PreparedStatement pstmt; for (id = 1; id < 10000; id ) { if (null == pstmt) pstmt = con.prepareStatement("UPDATE employees SET salay = ? WHERE id = ?"); pstmt.setBigDecimal(1, 150.00); pstmt.setInt(2, id); pstmt.executeQuery(); }
二者区别在于,不用绑定变量,则相当于反复解析、执行了1w个sql语句。使用绑定变量,解析sql语句只用了一次,之后的9999次复用第一次生成的执行计划。显然,后者效率会更高一些。
什么时候不应该/不必要使用绑定变量
- 如果你用数据仓库,一条大查询一跑几个小时,根本没必要做绑定变量,因为解析的消耗微乎其微。
- 变量对优化器产生执行计划有很重要的影响的时候:绑定变量被使用时,查询优化器会忽略其具体值,因此其预估的准确性远不如使用字面量值真实,尤其是在表存在数据倾斜(表上的数据非均匀分布)的列上会提供错误的执行计划。从而使得非高效的执行计划被使用。
全文索引
全文检索是对大数据文本进行索引,在建立的索引中对要查找的单词进行进行搜索,定位哪些文本数据包括要搜索的单词。因此,全文检索的全部工作就是建立索引和在索引中搜索定位,所有的工作都是围绕这两个来进行的。
建立全文索引中有两项非常重要,一个是如何对文本进行分词,一是建立索引的数据结构。分词的方法基本上是二元分词法、最大匹配法和统计方法。索引的数据结构基本上采用倒排索引的结构。
分词的好坏关系到查询的准确程度和生成的索引的大小。在中文分词发展中,早期经常使用分词方式是二元分词法,该方法的基本原理是将包含中文的句子进行二元分割,不考虑单词含义,只对二元单词进行索引。因此该方法所分出的单词数量较多,从而产生的索引数量巨大,查询中会将无用的数据检索出来,好处是算法简单不会漏掉检索的数据。之后又发展出最大匹配分词方法,该方法又分为正向最大分词和逆向最大分词。其原理和查字典类似,对常用单词生成一个词典,分析句子的过程中最大的匹配字典中的单词,从而将句子拆分为有意义的单词链。最大匹配法中正向分词方法对偏正式词语的分辨容易产生错误,比如“首饰和服装”会将“和服”作为单词分出。达梦数据库采用的是改进的逆向最大分词方法,该分词方法较正向正确率有所提高。最为复杂的是通过统计方式进行分词的方法。该方法采用隐式马尔科夫链,也就是后一个单词出现的概率依靠于前一个单词出现的概率,最后统计所有单词出现的概率的最大为分词的依据。这个方法对新名词和地名的识别要远远高于最大匹配法,准确度随着取样文本的数量的增大而提高。
二元分词方法和统计方法是不依赖于词典的,而最大匹配法分词方法是依赖于词典的,词典的内容决定分词结构的好坏。
全文检索的索引被称为倒排索引,之所以成为倒排索引,是因为将每一个单词作为索引项,根据该索引项查找包含该单词的文本。因此,索引都是单词和唯一记录文本的标示是一对多的关系。将索引单词排序,根据排序后的单词定位包含该单词的文本。
上面这个感觉介绍的不是特别好,可以看高性能mysql的第299页到第301页
-
Sqlserver——日常维护——DDL触发器(数据库级触发器)的使用方法
2019-03-27 15:25:101、普通的触发器的绑定对象为表,它定义了当一个表发生了【增】、【删】、【改】的DML语句时,默认执行的sql语句。 这里我们称之为表触发器,表触发器的用途很多,可以用作维持数据一致性的级联同步,和数据一致性...首先明确什么是DDL触发器?DDL触发器和普通的表触发器有什么区别?
1、普通的触发器的绑定对象为表,它定义了当一个表发生了【增】、【删】、【改】的DML语句时,默认执行的sql语句。
这里我们称之为表触发器,表触发器的用途很多,可以用作维持数据一致性的级联同步,和数据一致性,保证的数据的完整性;另外还通常被用作创建日志表使用。通过所定义的语句,当一个表发生增删改动作的时候,记录下每次DML语句的日志情况。
2、而DDL触发器的绑定对象是某个数据库,顾名思义,它是隶属于某个数据库的触发器,它定义了当一个数据库内的对象发生了 【修改】、【创建】、【删除】的执行的执行的sql语句。
这里我们称之为数据库触发器。(数据库对象:【表】、【视图】、【函数】、【触发器】、【存储过程】等)
使用DDL触发器,我们可以实现对数据库中的相关对象的变更历史进行记录,并进行管控
例如:对于一个事务性系统而言(例如ERP),可能会有很多开发人员在数据库上进行进行编程,由于需求变更、版本更替等一系列原因,我们会不停的对某个存储过程进行多次的修改并投入使用,而通常存储过程是无法像C#,JAVA等编程语言一样,可以进行代码管理,并有对应的版本更替,版本回滚等。但是当我们需要查看这个存储过程经历了哪些变动,每次修改了什么地方时,我们就无法系统性进行管理和查看(当然,可以人为的记录在excel等相关文档中)
这个时候就可以使用DDL触发器对这些相应对象的变更进行日志记录,并相关管控
下面是设置为某个数据库设置触发器变更日志记录的DDL语句
CREATE TRIGGER DLL_TRIGGER_CREATE_ALTER_DROP ON DATABASE FOR CREATE_TRIGGER, DROP_TRIGGER, ALTER_TRIGGER AS /* 本触发器只针对触发器的增删改,进行记录触发器的相关信息 */ IF OBJECT_ID('dbo.ddl_trigger_log', 'U') = NULL CREATE TABLE dbo.ddl_trigger_log ( rowid INT IDENTITY , EventType VARCHAR(20) , PostTime DATETIME , SPID INT , ServerName VARCHAR(255) , LoginName VARCHAR(255) , DatabaseName VARCHAR(255) , UserName VARCHAR(255), SchemaName VARCHAR(20) , ObjectName VARCHAR(255) , ObjectType VARCHAR(20) , CommandText NVARCHAR(MAX) , remark NVARCHAR(MAX) , commandtext_check INT ); DECLARE @EeventType VARCHAR(20), @PostTime DATETIME, @SPID INT, @ServerName VARCHAR(255), @LoginName VARCHAR(255), @DatabaseName VARCHAR(255), @UserName VARCHAR(255), @SchemaName VARCHAR(255), @ObjectName VARCHAR(255), @ObjectType VARCHAR(20), @CommandText NVARCHAR(MAX), @Remarks NVARCHAR(MAX), @Commandtest_check INT SET @EeventType=EVENTDATA().value('(/EVENT_INSTANCE/EventType)[1]','VARCHAR(20)') SET @PostTime=EVENTDATA().value('(/EVENT_INSTANCE/PostTime)[1]','DATETIME') SET @SPID=EVENTDATA().value('(/EVENT_INSTANCE/SPID)[1]','INT') SET @ServerName=EVENTDATA().value('(/EVENT_INSTANCE/ServerName)[1]','VARCHAR(255)') SET @LoginName=EVENTDATA().value('(/EVENT_INSTANCE/LoginName)[1]','VARCHAR(255)') SET @DatabaseName=EVENTDATA().value('(/EVENT_INSTANCE/LoginName)[1]','VARCHAR(255)') SET @UserName=EVENTDATA().value('(EVENT_INSTANCE/UserName)[1]','VARCHAR(255)') SET @SchemaName=EVENTDATA().value('(EVENT_INSTANCE/SchemaName)[1]','VARCHAR(255)') SET @ObjectName=EVENTDATA().value('(EVENT_INSTANCE/ObjectName)[1]','VARCHAR(255)') SET @ObjectType=EVENTDATA().value('(EVENT_INSTANCE/ObjectType)[1]','VARCHAR(255)') SET @CommandText=EVENTDATA().value('(EVENT_INSTANCE/TSQLCommand/CommandText)[1]','NVARCHAR(MAX)') INSERT INTO dbo.ddl_trigger_log ( EventType , PostTime , SPID , ServerName , LoginName , DatabaseName , UserName , SchemaName , ObjectName , ObjectType , CommandText , remark , commandtext_check ) SELECT @EeventType , @PostTime , @SPID , @ServerName , @LoginName , @DatabaseName , @UserName , @SchemaName , @ObjectName , @ObjectType , @CommandText , '' , 0;
执行了脚本之后,在该数据库上发生了任何关于触发器的ALTER、DROP、CREATE 语句都会记录在日志表中
详细的相关信息都可以通过日志表进行查看
-
mysql触发器trigger 实例详解
2018-09-07 11:33:20MySQL好像从5.0.2版本就开始支持触发器的功能了,5.7版本以上支持建立一个事件绑定多个触发器,本次博客就来介绍一下触发器,首先还是谈下概念性的东西吧: 什么是触发器 触发器是与表有关的数据库对象,在满足...MySQL好像从5.0.2版本就开始支持触发器的功能了,5.7版本以上支持建立一个事件绑定多个触发器,本次博客就来介绍一下触发器,首先还是谈下概念性的东西吧:
什么是触发器
触发器是与表有关的数据库对象,在满足定义条件时触发,并执行触发器中定义的语句集合。触发器的这种特性可以协助应用在数据库端确保数据的完整性。
举个例子,比如你现在有两个表【用户表】和【日志表】,当一个用户被创建的时候,就需要在日志表中插入创建的log日志,如果在不使用触发器的情况下,你需要编写程序语言逻辑才能实现,但是如果你定义了一个触发器,触发器的作用就是当你在用户表中插入一条数据的之后帮你在日志表中插入一条日志信息。当然触发器并不是只能进行插入操作,还能执行修改,删除。
创建触发器
创建触发器的语法如下:
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
其中,触发器名参数指要创建的触发器的名字
BEFORE和AFTER参数指定了触发执行的时间,在事件之前或是之后
FOR EACH ROW表示任何一条记录上的操作满足触发事件都会触发该触发器
创建有多个执行语句的触发器
CREATE TRIGGER 触发器名 BEFORE|AFTER 触发事件 ON 表名 FOR EACH ROW BEGIN 执行语句列表 END
其中,BEGIN与END之间的执行语句列表参数表示需要执行的多个语句,不同语句用分号隔开
tips:一般情况下,mysql默认是以 ; 作为结束执行语句,与触发器中需要的分行起冲突
为解决此问题可用DELIMITER,如:DELIMITER ||,可以将结束符号变成||
当触发器创建完成后,可以用DELIMITER ;来将结束符号变成;
mysql> DELIMITER || mysql> CREATE TRIGGER demo BEFORE DELETE -> ON users FOR EACH ROW -> BEGIN -> INSERT INTO logs VALUES(NOW()); -> INSERT INTO logs VALUES(NOW()); -> END -> || Query OK, 0 rows affected (0.06 sec) mysql> DELIMITER ;
上面的语句中,开头将结束符号定义为||,中间定义一个触发器,一旦有满足条件的删除操作就会执行BEGIN和END中的语句,接着使用||结束
最后使用DELIMITER ; 将结束符号还原
tigger_event:
load data语句是将文件的内容插入到表中,相当于是insert语句,而replace语句在一般的情况下和insert差不多,但是如果表中存在primary 或者unique索引的时候,如果插入的数据和原来的primary key或者unique相同的时候,会删除原来的数据,然后增加一条新的数据,所以有的时候执行一条replace语句相当于执行了一条delete和insert语句。
触发器可以是一条SQL语句,也可以是多条SQL代码块,那如何创建呢?
DELIMITER $ #将语句的分隔符改为$ BEGIN sql1; sql2; ... sqln END $ DELIMITER ; #将语句的分隔符改回原来的分号";"
在BEGIN...END语句中也可以定义变量,但是只能在BEGIN...END内部使用:DECLARE var_name var_type [DEFAULT value] #定义变量,可指定默认值 SET var_name = value #给变量赋值
NEW和OLD的使用:
根据以上的表格,可以使用一下格式来使用相应的数据:
NEW.columnname:新增行的某列数据 OLD.columnname:删除行的某列数据
说了这么多现在我们来创建一个触发器吧!
现在有表如下:
用户users表CREATE TABLE `users` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(255) CHARACTER SET utf8mb4 DEFAULT NULL, `add_time` int(11) DEFAULT NULL, PRIMARY KEY (`id`), KEY `name` (`name`(250)) USING BTREE ) ENGINE=MyISAM AUTO_INCREMENT=1000001 DEFAULT CHARSET=latin1;
日志logs表:
CREATE TABLE `logs` ( `Id` int(11) NOT NULL AUTO_INCREMENT, `log` varchar(255) DEFAULT NULL COMMENT '日志说明', PRIMARY KEY (`Id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='日志表';
需求是:当在users中插入一条数据,就会在logs中生成一条日志信息。
创建触发器:
DELIMITER $ CREATE TRIGGER user_log AFTER INSERT ON users FOR EACH ROW BEGIN DECLARE s1 VARCHAR(40)character set utf8; DECLARE s2 VARCHAR(20) character set utf8;#后面发现中文字符编码出现乱码,这里设置字符集 SET s2 = " is created"; SET s1 = CONCAT(NEW.name,s2); #函数CONCAT可以将字符串连接 INSERT INTO logs(log) values(s1); END $ DELIMITER ;
这里我用的navicat:
查看触发器
SHOW TRIGGERS语句查看触发器信息
Tip:
上面我用的navicat直接创建,如果大家用的mysql front,name这里会有个区别,我们删除刚才的触发器,在Mysql front中测试
drop trigger user_log;#删除触发器
打开Mysql Front:
mysql front在编译sql时,不用定义结尾分隔符,修改后的sql直接这样既可:
#DELIMITER $ CREATE TRIGGER user_log AFTER INSERT ON users FOR EACH ROW BEGIN DECLARE s1 VARCHAR(40)character set utf8; DECLARE s2 VARCHAR(20) character set utf8; SET s2 = " is created"; SET s1 = CONCAT(NEW.name,s2); #函数CONCAT可以将字符串连接 INSERT INTO logs(log) values(s1); END #$ #DELIMITER ;
这里再啰嗦几句:
tips:SHOW TRIGGERS语句无法查询指定的触发器
在triggers表中查看触发器信息
SELECT * FROM information_schema.triggers;
结果显示了所有触发器的详细信息,同时,该方法可以查询制定触发器的详细信息
SELECT * FROM information_schema.triggers WHERE TRIGGER_NAME='user_log';
tips:所有触发器信息都存储在information_schema数据库下的triggers表中
可以使用SELECT语句查询,如果触发器信息过多,最好通过TRIGGER_NAME字段指定查询
回到上面,我们创建好了触发器,继续在users中插入数据并查看数据:
insert into users(name,add_time) values('周伯通',now());
好吧,我们再来查看一下logs表吧!
通过上面的例子,可以看到只需要在users中插入用户的信息,日志会自动记录到logs表中,这也许就是触发器给我带来的便捷吧!
限制和注意事项
触发器会有以下两种限制:
1.触发程序不能调用将数据返回客户端的存储程序,也不能使用采用CALL语句的动态SQL语句,但是允许存储程序通过参数将数据返回触发程序,也就是存储过程或者函数通过OUT或者INOUT类型的参数将数据返回触发器是可以的,但是不能调用直接返回数据的过程。
2.不能再触发器中使用以显示或隐式方式开始或结束事务的语句,如START TRANS-ACTION,COMMIT或ROLLBACK。
注意事项:MySQL的触发器是按照BEFORE触发器、行操作、AFTER触发器的顺序执行的,其中任何一步发生错误都不会继续执行剩下的操作,如果对事务表进行的操作,如果出现错误,那么将会被回滚,如果是对非事务表进行操作,那么就无法回滚了,数据可能会出错。
总结
触发器是基于行触发的,所以删除、新增或者修改操作可能都会激活触发器,所以不要编写过于复杂的触发器,也不要增加过得的触发器,这样会对数据的插入、修改或者删除带来比较严重的影响,同时也会带来可移植性差的后果,所以在设计触发器的时候一定要有所考虑。
触发器是一种特殊的存储过程,它在插入,删除或修改特定表中的数据时触发执行,它比数据库本身标准的功能有更精细和更复杂的数据控制能力。
数据库触发器有以下的作用:
1.安全性。可以基于数据库的值使用户具有操作数据库的某种权利。
# 可以基于时间限制用户的操作,例如不允许下班后和节假日修改数据库数据。
# 可以基于数据库中的数据限制用户的操作,例如不允许股票的价格的升幅一次超过10%。
2.审计。可以跟踪用户对数据库的操作。
# 审计用户操作数据库的语句。
# 把用户对数据库的更新写入审计表。
3.实现复杂的数据完整性规则
# 实现非标准的数据完整性检查和约束。触发器可产生比规则更为复杂的限制。与规则不同,触发器可以引用列或数据库对象。例如,触发器可回退任何企图吃进超过自己保证金的期货。
# 提供可变的缺省值。
4.实现复杂的非标准的数据库相关完整性规则。触发器可以对数据库中相关的表进行连环更新。例如,在auths表author_code列上的删除触发器可导致相应删除在其它表中的与之匹配的行。
# 在修改或删除时级联修改或删除其它表中的与之匹配的行。
# 在修改或删除时把其它表中的与之匹配的行设成NULL值。
# 在修改或删除时把其它表中的与之匹配的行级联设成缺省值。
# 触发器能够拒绝或回退那些破坏相关完整性的变化,取消试图进行数据更新的事务。当插入一个与其主健不匹配的外部键时,这种触发器会起作用。例如,可以在books.author_code 列上生成一个插入触发器,如果新值与auths.author_code列中的某值不匹配时,插入被回退。
5.同步实时地复制表中的数据。
6.自动计算数据值,如果数据的值达到了一定的要求,则进行特定的处理。例如,如果公司的帐号上的资金低于5万元则立即给财务人员发送警告数据。
-
mysql触发器介绍和使用
2020-02-18 14:44:08触发器是mysql数据库针对某张表发生增删改操时自动执行的一段语句集合,它是跟某张表关联绑定的,不像存储过程那种需要被动调用。触发器可以用来检验数据完整性,日志跟踪记录等。注意:不能在mysql本身系统数据库的...触发器是mysql数据库针对某张表发生增删改操时自动执行的一段语句集合,它是跟某张表关联绑定的,不像存储过程那种需要被动调用。触发器可以用来检验数据完整性,日志跟踪记录等。注意:不能在mysql本身系统数据库的表上创建触发器,要在其他数据库的表上创建。
创建触发器的结构:
create trigger trigger_name
before/after insert/update/delete
on table_name
for each row #行级触发器
begin
具体语句...
end
触发器针对的是数据库中表的每一行记录,每行数据在操作前后都会有一个对应的状态,触发器将没有操作之前的状态保存到 old 关键字中,将操作后的状态保存到 new 中
语法:old/new.字段名
需要注意的是,old 和 new 不是所有触发器都有
触发器类型 new和old的使用
INSERT型触发器 没有 old,只有 new,new 表示将要(插入前)或者已经增加(插入后)的数据
UPDATE型触发器 既有 old 也有 new,old 表示更新之前的数据,new 表示更新之后的数据
DELETE型触发器 没有 new,只有 old,old 表示将要(删除前)或者已经被删除(删除后)的数据举例说明,在mysql里testdb数据库下的两个表,person以及person_log(是记录每次在person表里修改操作的日志)
mysql> use testdb;
mysql> show create table person\G;
*************************** 1. row ***************************
Table: person
Create Table: CREATE TABLE `person` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` text CHARACTER SET utf8,
`addr` text CHARACTER SET utf8,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1
1 row in set (0.00 sec)ERROR:
No query specifiedmysql> show create table person_log\G;
*************************** 1. row ***************************
Table: person_log
Create Table: CREATE TABLE `person_log` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`operation` varchar(20) NOT NULL,
`optime` datetime NOT NULL,
`opinfo` varchar(100) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8
1 row in set (0.01 sec)先创建一个在delete操作后,发生的触发器person_delaft_trigger。这个触发器的作用,就是当在person表里删除记录后,在日志表person_log里插入一条记录,把删除的信息输入。
mysql> delimiter $
mysql> create trigger person_delaft_trigger after delete on person for each row insert into person_log(operation,optime,opinfo) values('delete',now(),concat('del row: ',old.name,' ',old.addr))$ #这里是delete操作,只有old关键字,记录的是删除的记录数据
刚开始的表数据:
当我们进行一个删除操作后:
可以看到在person_log日志表就有一条记录了。
下面,我们再创建2个触发器,分别是在insert操作之前和之后,通过show triggers\G;可以看到当前的所有触发器信息:
在插入之前的触发器,执行语句是:
if new.name='andy' then
set new.name='haha';
end if意思是,如果name字段是andy,就改为haha。
在插入之后的触发器,执行语句是:
begin insert into person_log(operation,optime,opinfo) values('insert',now(),concat('new row: ',new.name,' ',new.addr)); end
因为是insert操作,所以是new关键字,代表的是新记录。
这个语句就是在person_log日志表里新建一条日志,把该条插入的数据写入。
测试执行下:
可以看到,我们连着插入两条数据记录在person表,第2条数据记录因为name字段是andy,所以会调用插入前的触发器,最终在表里实际插入的是haha。而插入后的触发器也执行了,在person_log表里插入了两条日志记录。
还有一个update更新的触发器,这里不再说明了,它是有old和new两个关键字,分别表示更新前的记录和更新后的记录。
最后,删除触发器指令:drop trigger 触发器名字,查看某个触发器信息:show create trigger 触发器名字\G,查看所有触发器信息:show triggers\G;
-
增量同步-spring batch(6)动态参数绑定与增量同步
2019-06-11 13:52:21增量同步-spring batch(6)动态参数绑定与增量同步 ...增量同步简述3.1 基于源数据的`CDC`3.2 基于触发器的`CDC`3.3 基于快照的`CDC`3.4 基于日志的`CDC`3.5 本示例增量同步方法说明4.Spring Batch动态参数绑定4.1 ... -
精通Oracle PL/SQL--详细书签版
2012-08-21 13:06:287.3.2 归档日志目录下的空闲空间 304 7.3.3 监控数据库中的空闲空间 305 7.3.4 小结 306 7.4 历史数据包 306 7.4.1 数据库大小 307 7.4.2 数据库会话 309 7.4.3 资源限制 310 7.4.4 小结 312 7.5 小结 312 ... -
Oracle 从入门到精通视频教程(11G版本)(ppt)
2012-11-03 13:09:13《Oracle 从入门到精通》中的视频教程和PPT资料。...使用绑定的方式连接Oracle 使用写代码的方式连接Oracle 第22章-在Java中连接Oracle JDBC与ODBC简介 Thin方式连接Oracle JDBC-ODBC桥连接Oracle -
Oracle Database 11g完全参考手册--详细书签版
2013-02-03 10:58:39CruiseYoung提供的带有详细书签的电子书籍目录 ... 特别说明:该版本是目前网络上最全的版本:修正了所有缺页和错页的问题。 Oracle Database 11g完全参考手册 基本信息 原书名: Oracle Database 11g The Complete ... -
一款非常好的WPF编程宝典2010 源代码
2014-04-14 09:57:419.4.4 向日志添加自定义项 221 9.4.5 页函数 225 9.5 XAML浏览器应用程序 227 9.5.1 XBAP应用程序的运行要求 228 9.5.2 创建XBAP应用程序 229 9.5.3 部署XBAP应用程序 230 9.5.4 更新XBAP应用程序 231 9.5.5 ... -
WPF编程宝典 part1
2015-07-20 23:33:5922.2.2 将DataSet对象绑定到TreeView 控件 617 22.2.3 即时创建节点 618 22.3 DataGrid控件 621 22.3.1 改变列的尺寸与重新安排列 622 22.3.2 定义列 623 22.3.3 设置列的格式和样式 628 22.3.4 设置行的格式 629 ... -
C# 3.0与.NET 3.5高级编程
2013-05-15 14:12:535.3.5 通过绑定浏览数据库记录 93 5.3.6 用LINQ查询LINQ to SQL类 95 5.3.7 修改数据库记录 96 5.4 小结 98 第6章 LINQ To XML——支持LINQ语言与 XML语言的交互 99 6.1 LINQ to XML概述 99 6.1.1 什么是LINQ to XML... -
Oracle11g从入门到精通2
2014-06-04 13:47:105.2.6 使用绑定变量 5.2.7 跟踪语句 5.3 设置SQL*Plus环境 5.3.1 SHOW命令 5.3.2 SET命令 5.4 SQL*Plus环境介绍 5.4.1 存储SQL*Plus环境 5.4.2 假脱机输出 5.4.3 联机帮助 5.5 使用SQL*Plus格式化... -
SQL Server 2008实战(SQL Server程序员和DBA不可或缺的权威参考手册)--详细书签版
2013-02-06 11:52:19和传统的 t-sql书籍不同,本书以独特的 “技巧 ”形式来介绍知识点,涵盖了数据处理(增删改、视图、索引、存储过程、触发器等)、数据应用(web服务、 clr集成、分布式查询等)和数据库配置(主体、安全、数据库... -
SQL Server 2008高级程序设计 5/6
2012-03-03 19:33:1411.2 SQL Server日志的工作方式 11.3 锁和并发 11.4 设置隔离级别 11.5 处理死锁(也称作“A 1205”) 11.6 小结 第12章 触发器 12.1 触发器的含义 12.2 为数据完整性规则使用触发器 12.3 ... -
C#高级编程(第6版).(清华出版.李铭译.黄静审校).part1
2016-07-13 17:41:2524.1.4 方法绑定 24.1.5 数据类型 24.1.6 注册 24.1.7 线程 24.1.8 错误处理 24.1.9 事件处理 24.2 编组 24.3 在.NET客户程序中使用COM组件 24.3.1 创建COM组件 24.3.2 创建Runtime Callable Wrapper 24.3.3 使用RCW... -
C#高级编程(第6版)
2011-05-11 11:10:3018.2.1 事件日志体系架构 18.2.2 事件日志类 18.2.3 创建事件源 18.2.4 写入事件日志 18.2.5 资源文件 18.3 性能监控 18.3.1 性能监控类 18.3.2 性能计数器的构建 18.3.3 添加PerformanceCounter... -
C#高级编程(第6版) part2.
2009-10-17 13:17:5318.2.1 事件日志体系架构 18.2.2 事件日志类 18.2.3 创建事件源 18.2.4 写入事件日志 18.2.5 资源文件 18.3 性能监控 18.3.1 性能监控类 18.3.2 性能计数器的构建 18.3.3 添加PerformanceCounter... -
C#高级编程(第9版).(清华出版.李铭译.黄静审校).part2
2016-07-15 20:45:2319.6.3 绑定到程序集版本 19.6.4 发行者策略文件 19.6.5 运行库的版本 19.7 在不同的技术之间共享程序集 19.7.1 共享源代码 19.7.2 可移植类库 19.8 小结 第20章 诊断 20.1 诊断概述 20.2 代码协定 20.2.1 前提... -
C#高级编程(第9版).(清华出版.李铭译.黄静审校).part1
2016-07-15 20:42:3719.6.3 绑定到程序集版本 19.6.4 发行者策略文件 19.6.5 运行库的版本 19.7 在不同的技术之间共享程序集 19.7.1 共享源代码 19.7.2 可移植类库 19.8 小结 第20章 诊断 20.1 诊断概述 20.2 代码协定 20.2.1 前提... -
C#高级编程(第9版).(清华出版.李铭译.黄静审校).part3
2016-07-15 20:48:0419.6.3 绑定到程序集版本 19.6.4 发行者策略文件 19.6.5 运行库的版本 19.7 在不同的技术之间共享程序集 19.7.1 共享源代码 19.7.2 可移植类库 19.8 小结 第20章 诊断 20.1 诊断概述 20.2 代码协定 20.2.1 前提... -
深入解析SQL SERVER 2008(附源代码)
2014-10-20 09:50:201.5.2 将计划程序绑定到CPU中 17 1.5.3 专用管理员连接(DAC) 20 1.6 内存 21 1.6.1 缓冲池与数据缓存 21 1.6.2 访问内存中的数据页 21 1.6.3 管理数据缓存中的页面 22 1.6.4 可用缓冲区列表和惰性编写... -
[Csharp高级编程(第6版)].(美)内格尔.扫描版.pdf
2013-08-09 10:39:02另外,还增加了一些全新的章节,包括LINQ、SQL、ADO.NET实体、Windows Communication Foundation、Windows Workflow Foundation、Windows Presentation Foundation、数组、系统事务处理、跟踪、事件日志等,使读者能... -
C#开发实战1200例(第2卷.完整版)(清华出版.王小科.王军).part2
2016-06-17 07:56:52实例280 update触发器在系统日志中的应用 实例281 使用delete触发器删除员工薪水信息 实例282 触发器的嵌套使用 使用283 使用递归触发器实现每次删除一条记录功能 实例284 使用触发器删除相关联的两表间的数据 7.5 ... -
深入解析SQL Server 2008(微软SQL Server开发团队必读之作)--随书源代码
2013-02-06 14:13:171.5.2 将计划程序绑定到CPU中 17 1.5.3 专用管理员连接(DAC) 20 1.6 内存 21 1.6.1 缓冲池与数据缓存 21 1.6.2 访问内存中的数据页 21 1.6.3 管理数据缓存中的页面 22 1.6.4 可用缓冲区列表和惰性编写... -
C#.net_经典编程例子400个
2013-05-17 09:25:3068 实例059 在ListBox控件间交换数据 68 实例060 将数据库数据添加到组合框中 70 实例061 借助绑定控件实现数据选择录入 71 实例062 ListBox拒绝添加重复信息 72 2.6 选择类控件应用 73... -
MySQL 5权威指南(第3版)--详细书签版
2013-02-05 15:44:005.3.7 Server Logs模块(查看服务器日志) 72 5.3.8 Backup模块(制作数据库备份) 72 5.3.9 Restore模块(用备份恢复数据库) 73 5.3.10 Replication Status模块(查看镜像机制的工作状态) 74 5.3.11 ... -
Oracle 数据库管理艺术:11g新特性(世界级Oracle专家权威力作)--详细书签版
2013-02-06 17:57:474.1.2 更快的DML触发器 138 4.1.3 自适应游标共享 138 4.2 新的结果高速缓存功能 140 4.2.1 使用服务器结果高速缓存提高性能 140 4.2.2 管理查询结果高速缓存 148 4.2.3 PL/SQL函数结果高速缓存 150 4.2.4 内... -
高性能MySQL(第3版).part2
2016-02-17 23:37:061.3.3事务日志10 1.3.4MySQL中的事务10 1.4多版本并发控制12 1.5MySQL的存储引擎13 1.5.1InnoDB存储引擎16 1.5.2MyISAM存储引擎17 1.5.3MySQL内建的其他存储引擎19 1.5.4第三方存储引擎22 1.5.5选择合适的... -
C#程序开发范例宝典电子书从1-471例后面的暂时没有
2008-10-16 21:15:36实例100 使用FileSystemWatcher组件监视系统日志文件是否被更改 140 3.5 HelpProvider组件 142 实例101 使用HelpProvider组件调用帮助文件 142 3.6 Process组件 143 实例102 使用Process组件访问本地进程 ... -
ASP.NET开发实战1200例(第1卷).part2
2016-06-11 20:12:37实例191 Eval()方法绑定日志并用“…”代替超长内容 305 实例192 双向绑定Bind()方法实现更新最新电影信息 306 实例193 绑定DataTable对象显示银行月利息及本息 307 7.2 GridView控件基本应用 308 实例194 GridView...
-
用Go语言来写区块链(一)
-
shell脚本编译uboot,Kernel,rootfs指定名保存到指定文件夹
-
接口组成更新与方法引用
-
Graph-based reasoning model for multiple relation extraction.pdf
-
MySQL 备份与恢复详解(高低版本 迁移;不同字符集 相互转换;表
-
软件开发的含义是什么,基础知识包含哪些?
-
迈好软件开发规范管理第一步:软件配置管理
-
编码大规模MIMO系统的高效MMSE-PIC检测方案
-
Scrum团队经历,如何在scrum中进行风险规避
-
access应用的3个开发实例
-
RabbitMQ的消息发布及消费者的WireShark抓包预览
-
Mybatis配置-属性(properties)
-
基于用户点击数据的细粒度图像识别方法概述
-
基于透射相位梯度超表面的宽带频率扫描欺骗表面等离子极化平面天线
-
Docker从入门到精通
-
MySQL 高可用工具 DRBD 实战部署详解
-
Galera 高可用 MySQL 集群(PXC v5.6 + Ngin
-
HTML5设计原理
-
【硬核】一线Python程序员实战经验分享(1)
-
算法设计 Algorithm Design Solution 7.27 7.31 7.39