Maison  >  Questions et réponses  >  le corps du texte

mysql - 触发器的实际使用场景, 可能也就是这个了, 一起讨论还有没有别的

触发器的实际使用场景大体说来就是帮你方便的迁移数据, 不过最好不要和业务紧密结合, 因为一个事务的的一部分在java那边, 另另一部分在触发器中是无法很方便的调试/排查/维护的, 唯有一个场景, 就是不想物理删数据的时候

很久以前有个不成文的规定就是, 不要物理删除数据, 所有表都要加上is_delete这个字段来标识某行数据是否被物理删除, 但是当遇到有唯一索引的时候, 这个规则就歇菜了, 因为, 比如name是唯一索引, 当用户添加xiaoming后, 然后删除xiaoming, 这时is_delete = Y,但是再次重新添加xiaoming就不可以了, 因为违反了唯一约束

因此, 这种情况, 就不要更新is_delete了, 而是利用 after delete 类型的触发器将数据迁移到另外的一张表, 比如 user_del 中, 他的字段与user表一致, 只不过多了个记录插入数据时间的字段

大家还有没有其他使用场景呢???????

ringa_leeringa_lee2716 Il y a quelques jours639

répondre à tous(2)je répondrai

  • 大家讲道理

    大家讲道理2017-04-17 16:42:51

    首先关于触发器,很多大公司是禁止使用的,一是可移植性差,二是影响性能,这也是我强烈主张的。

    然后着重讨论下非物理删除的情况吧。碰到有唯一键约束并且有is_delete这种列的表,确实特别蛋疼的。我在项目中是这么处理的,假设用户表user有这么几列:

    • id (主键)

    • username (唯一键)

    • ...

    • is_delete

    插入时,如果唯一键冲突,那就查一下有没有被删掉的同名用户:

    SELECT id FROM user WHERE username = ? AND is_delete = 1
    

    有同名的话(并且得到了id)做一个UPDATE操作,就当是恢复删除了:

    UPDATE user SET ..., is_delete = 0 WHERE id = ?
    

    然后蛋疼的问题就来了,既然用户有删除的需求(说实话这种需求是不多见的),也就有改用户名的需求。改用户名遇到主键冲突,并且已存在的用户是已被逻辑删除的,那么你到底是让他改还是不让他改呢?

    权宜之计是把唯一键也做成“非物理”的,每次创建用户前都去查一下,查到没有被删除的同名用户,就允许创建,改名也一样。不过这种操作可能要做成事务了,因为在并发高的情况下,完全可能SELECT的时候还没重名,但INSERT就重名了。

    répondre
    0
  • 大家讲道理

    大家讲道理2017-04-17 16:42:51

    楼上的问题
    "改用户名遇到主键冲突,并且已存在的用户是已被逻辑删除的,那么你到底是让他改还是不让他改呢?"
    有个办法 以前在小项目使用过,不知道大的项目可不可行。
    每个表都使用自增ID,主键的约束使用 主键+"is_delete" 的约束。

    répondre
    0
  • Annulerrépondre