6

前言

当我们数据库变得绝对复杂时,关联删除变得不切实际,这时我们想到了使用软删除替代删除,但是软删除并没有删除数据,数据依旧存在。当我们表内有唯一字段时,例如用户表中的username字段,我们删除原先的用户,相同username的用户便无法注册。这是我们所期待的。最好的解决办法就是,再设置deleted_at字段,记录“删除”一条数据的时间,将以username为唯一索引变为username与deleted_at共同为唯一索引。唯一索引就是不允许出现username与çsername相同的数据,当删除数据时,deleted_at改变,username可以再次添加,并可以多次删除。如何当“删除”数据时改变deleted_at就是用到了我们的触发器。

触发器

触发器类似与我们的切面编程。在一个特定的事件执行前后,会触发我们提前设置好的触发器。
我们打开navicat,随便点击一个数据表,点击设计表

image.png
triggers就是我们的触发器,点击左上角加号创建一个触发器。
name:随便起一个名字就好
Time:分为after和before,顾名思义,在什么时候触发。之前或者之后。
事件:后面是一个三选一的选项,insert(增加),update(更新),delete(删除)。由哪一类事件触发。
最下面的是触发的sql语句。

new和old

该关键字,表示触发了触发器的那一行数据。
INSERT触发器中,NEW用来表示将要(BEFORE)或已经(AFTER)插入的新数据。
UPDATE触发器中,OLD用来表示将要或已经被修改的原数据,NEW用来表示将要或已经修改为的新数据。
DELETE触发器中,OLD用来表示将要或已经被删除的原数据。

另外,OLD 是只读的,而 NEW 则可以在触发器中使用 SET 赋值,这样不会再次触发触发器,造成循环调用。

触发事件

回归我们的需求,我们希望“删除”的时候触发触发器,使得deleted_at变为当前时间。但是,我们的“删除”并不是真正的删除,而是软删除,也就是更新这条数据的deleted字段为0。所以我们应该选择绑定update触发器,并选择在before时触发
image.png
然后是设置触发sql语句。我们不希望只要执行更新操作就执行,只有在软删除时执行,所以我们需要加一个判断语句触发执行。
然后在根据报错提示修改语法,最后是这样的

BEGIN
IF new.deleted = 1 THEN
        SET NEW.deleted_at = CURRENT_TIMESTAMP;
END IF;
END

当deleted为1的时候触发。

验证效果如下
image.png
如果语句这样写

BEGIN
IF new.deleted = 1 THEN
        UPDATE `tag` SET `deleted_at` = CURRENT_TIMESTAMP;
END IF;
END

再去执行他会报错。
image.png
大概意思就是你不能执行update操作因为他正在被触发器调用。这应该是mysql的一种保护机制,防止触发器无限调用。
但是我想用after触发器的时候遇到了困惑,两种写法都不行,new和old貌似对于after触发器来说不认可。这里没搞懂她的语法是什么。

总结

数据库也蕴含着很大的学问。下学期也要学数据库了。JPA给了我们很大便利,这也使得遇到原生的mysql就不会了。本来还想写一篇索引来着,但是有个问题一直没有解决,也写不出来什么东西。


小强Zzz
1.2k 声望32 粉丝