触发器的实际使用场景大体说来就是帮你方便的迁移数据, 不过最好不要和业务紧密结合, 因为一个事务的的一部分在java那边, 另另一部分在触发器中是无法很方便的调试/排查/维护的, 唯有一个场景, 就是不想物理删数据的时候
很久以前有个不成文的规定就是, 不要物理删除数据, 所有表都要加上is_delete这个字段来标识某行数据是否被物理删除, 但是当遇到有唯一索引的时候, 这个规则就歇菜了, 因为, 比如name是唯一索引, 当用户添加xiaoming后, 然后删除xiaoming, 这时is_delete = Y,但是再次重新添加xiaoming就不可以了, 因为违反了唯一约束
因此, 这种情况, 就不要更新is_delete了, 而是利用 after delete 类型的触发器将数据迁移到另外的一张表, 比如 user_del 中, 他的字段与user表一致, 只不过多了个记录插入数据时间的字段
大家还有没有其他使用场景呢???????
首先关于触发器,很多大公司是禁止使用的,一是可移植性差,二是影响性能,这也是我强烈主张的。
然后着重讨论下非物理删除的情况吧。碰到有唯一键约束并且有is_delete这种列的表,确实特别蛋疼的。我在项目中是这么处理的,假设用户表user有这么几列:
id (主键)
username (唯一键)
...
is_delete
插入时,如果唯一键冲突,那就查一下有没有被删掉的同名用户:
有同名的话(并且得到了id)做一个UPDATE操作,就当是恢复删除了:
然后蛋疼的问题就来了,既然用户有删除的需求(说实话这种需求是不多见的),也就有改用户名的需求。改用户名遇到主键冲突,并且已存在的用户是已被逻辑删除的,那么你到底是让他改还是不让他改呢?
权宜之计是把唯一键也做成“非物理”的,每次创建用户前都去查一下,查到没有被删除的同名用户,就允许创建,改名也一样。不过这种操作可能要做成事务了,因为在并发高的情况下,完全可能SELECT的时候还没重名,但INSERT就重名了。
楼上的问题
"改用户名遇到主键冲突,并且已存在的用户是已被逻辑删除的,那么你到底是让他改还是不让他改呢?"
有个办法 以前在小项目使用过,不知道大的项目可不可行。
每个表都使用自增ID,主键的约束使用 主键+"is_delete" 的约束。