发表于: 2017-12-01 14:41:26
1 659
今天完成的事情:
仔细看了任务要求,需要将create_at 和updata_at 设置为long类型,也就是mysql中的bigint类型,如此一来,使用timestamp并不算完全符合要求,
首先考虑了timestamp转换long类型,但是由于在建表语句中设置的default CURRENT_TIMESTAMP 和 on update CURRENT_TIMESTAMP,没有办法在建表语句中完成转换,所以只有考虑其他途径,由此发现了SQL触发器。
简单的说,触发器就是在表格发生某些操作的时候,比如insert,delete,update的时候,可以自由设定对数据库中的表格进行某些sql语句的操作,这里的表格并不局限与上述发生insert、delete、update操作的表格,也就是说当表一出发了条件,可以在表二中进行操作。简单的用法如下:
delimiter $
create trigger trigger-name //红字表示出发器的名字
// 绿字表示的是下面begin 和 end 范围中的sql语句是在触发条件发生之前还是之后执行,蓝色部分表示触发条件,在某个表中发生的操作。
before/after insert/delete/update on table_name
//查到说,for eacj row 这一句对于mysql来说是必须的,换句话说对于其他数据库可能还有不一样的情况,我没有继续深究了,暂且记住。
for each row
//固定格式,begin和end中间的sql语句为触发条件后的执行语句
begin
……sql语句……; //这里可以有多条sql语句,每一条语句用分号;隔开,复杂一点的还可以进行条件判断等等,时间有限依然没有深究,当用到的时候再研究
end$
//对于mysql来说,分号就是一段操作的终止符,但是触发器的定义中需要保证整个定义的完整性,因而在begin和end中间的sql语句的分号并不能作为终止,遇到定义新的终止符,这里我选择了$符号作为整个定义的终止符,只有这样才能保证定义trigger的完整性。
delimiter ;
我的实际例子如下:
师兄的建表语句:
create table tab_teacher5(
t_id int primary key auto_increment,
t_name varchar(20),
create_at bigint, //此处使用的是bigint 而非之前的timestamp
update_at timestamp default current_timestamp on update current_timestamp
);
触发器的定义:
delimiter $ // 这里没有分号
create trigger t_tab_teacher_insert
before insert on tab_teacher5①
for each row
begin
set new.create_at=unix_timestamp(now());
end$
delimiter ; //这里恢复终止符为分号
需要特别注意的是遇到的几个问题:
1、采用long类型来储存时间戳的本质是计算当前系统时间到1970-01-01的毫秒数,所以在表格中记录的是一个很大的数字,并不能直接看到具体的时间,这样其实并不是非常方便,在插10000条记录的时间上,两种方式没什么差异。
2、存储的时候我采用了转换函数unix_timestamp(),这也是我第一次接触。
3、在begin和end中间编写sql语句的时候出现了一些错误,
思路一:在插入数据之后,修改插入数据栏中的create_at ,使其的值为当前的时间;
delimiter $
create trigger t_tab_teacher_insert1
after insert on tab_teacher5
for each row
begin
update tab_teacher5 set new.create_at=unix_timestamp(now());
end$
delimiter ;
添加的过程触发器的过程没有问题,但是插入的时候报错:
由于表格调用了触发器的中的语句,你无法对表格执行update操作。
解决方法:去掉update tab_teacher5,直接写set new.create_at=unix_timestamp(now());
思路二:在插入数据之后记录插入时间,所以在上面的①处,我最先写的是 after insert on tab_teacher5,执行报错,报错信息为:
updating of new row is not allowed in after trigger 在after类型的触发器中不能对新插入的条目进行update操作,
解决方法:将after改为before。
基于这两个问题,查了一下别人总结的帖子:https://www.cnblogs.com/zejin2008/p/4643761.html
Before与After区别:
before:(insert、update)可以对new进行修改,after不能对new进行修改,两者都不能修改old数据。
对于INSERT语句, 只有NEW是合法的;
对于DELETE语句,只有OLD才合法;
对于UPDATE语句,NEW、OLD可以同时使用。
after—是在记录操纵之后触发,是先完成数据的增删改,再触发,触发的语句晚于监视的增删改操作,无法影响前面的增删改动作
before—是在记录操纵之前触发,是先完成触发,再增删改,触发的语句先于监视的增删改,我们就有机会判断,修改即将发生的操作,如:我们在触发之前需要判断new值和old值的大小或关系,如果满足要求就触发,不通过就修改再触发;如:表之间定义的有外键,在删除主键时,必须要先删除外键表,这时就有先后之分,这里before相当于设置了断点,我们可以处理删除外键。
能理解,过几天估计就忘了,用到的时候能研究出来。
评论