这两天写项目,有个要求是记录用户登录登出操作,把这些操作写到日志表里去,我觉得这个功能用MySQL的触发器来写,更方便一些,所以在这整理了一下这一过程。
在这里,我就不把项目的所以代码都粘贴过来了,项目用的是hibernate,这里我创建两个简单的表来演示一下这个过程。
1:登录表,记录用户的账号,密码以及在线状态,0表示不在线,1表示在线。对status进行默认约束,默认值就是0.
create table login( id int not null primary key auto_increment, password varchar(20) not null, status int not null default 0 )
看一下表结构:
2:日志表,记录执行操作的时间和执行了什么操作,这里我写的更简单,时间和用户ID
create table log( id int not null primary key auto_increment, operationTime timestamp, login_id int );
可以看出,这里的日期时间类型,我用的是timestamp,这个类型可以自动生成你进行相应记录操作的时间,当然,你可以更改具体的操作,比如说,在Insert的时候才自动生成,或者只有在delete的时候自动生成。log表的信息只有插入和查询,是不会更新的。所以涉及不到timestamp的其他内容。
3:触发器:我们的触发器要实现的功能是 在修改表login的status记录的时候,向log表插入一条数据,记录当前时间和用户。
delimiter $ create trigger status after update on login for each row begin if old.status<>new.status then insert into log(login_id) values(new.id); end if; end
1)delimiter $ 的意思是告诉告诉MySQL解释器,用哪个符号作为结尾。通常用的都是; 一到分号就开始执行MySQL语句了,用了delimiter $就说明在遇到$的时候执行。
2)触发器trigger语法
create trigger triggerName
after/before insert/update/delete on 表名
for each row (这句话在MySQL是固定的)
begin
sql语句;
end;
3)after/before
这个是触发程序的时间,是在后面的操作执行之前 还是执行之后,当然 这里说的执行是正确执行。
4)insert/update/delete
这个是指明激发触发器的事件类型,是对表进行了插入 更新 或者是删除操作 ,才能触发这个程序。显然上面的程序是针对更新操作而言的。
5)old new
old.列名指的是原来的值 new.列名指的是新的值。我们把new.id赋值给了log表的Login_id。
6)if then end if
这是个程序块,在begin end之间可以写简单的sql语句 也可以写程序块。这也是为什么要delimiter $的原因,如果还是默认的; MySQL解释器读到这的时候就开始执行了,显然这是错误的。
4:执行效果
创建触发器
向login表中插入数据,别忘了把;改回来
查了一下log表 是没有记录的。
对表login执行update操作
再查看log表 是有结果的。而且timestamp自动更新了当前时间。
5:写个插入的触发器试试看,刚才的是update,我们插入之后log表是没有记录的,现在再写一个触发器。
delimiter $ create trigger insertLogin after insert on login for each row begin insert into log(login_id) values(new.id); end insert into login values(default,‘14785‘,0);