Laravel 中 deleted_at 的默认设定与唯一约束产生冲突,该如何解决?
-
deleted_at
默认值为null
,这一点在给表创建唯一约束的时候有冲突,MySQL
和PgSQL
(其他数据库暂不了解)中唯一约束允许多个null
值存在。 -
使用软删除可能碰到的问题:如果表中有唯一约束的字段,比如
User
表的username
,一行记录被软删除后,username
已经被占用了,新的数据不能使用该username
。而如果将deleted_at
加入唯一约束,由于deleted_at
默认值是null
,MySQL
和PgSQL
下唯一值是不算NULL的,即唯一值列出现多个NULL值都不会报错。 -
这就有点尴尬了,如果一张表想加入唯一约束,就不能使用软删除功能,要不然就重写软删除逻辑,给
deleted_at
设置一个默认值,但这应该有违Laravel设计的本意,Laravel内是不是提供其他解决方式?我不是很熟悉,特此请教 :pray:
我的理解,username 和 deleted_at 联合唯一,不知道是不是你想要的答案?
其实,数据库的约束完全可以用 PHP 来处理的,这样还更灵活
@LiCxi 这个方案文里说了,
deleted_at
值是null
时唯一约束失效,所以才有这个问题@ivothgle 但是更不安全,请求量增多时,容易出现一些类似并发的问题,也会影响性能
@Herjew 如果不是业务上必要用唯一索引来做数据限制,性能上普通索引效率更好。
@terranc 索引和唯一约束分开来谈,这里主要谈:如果设置了
唯一约束
,deleted_at
的存在会让唯一约束
失效。那么,如果一张表既需要唯一约束
,也需要具备软删除
能力,该如何解决?我理解 Laravel 的这个软删除就是为了我们能够对数据进行撤消、恢复使用的,假定我们有可能对数据进行撤消操作,那就不应该给 deletet_at 设置唯一索引。
那如果我们不需要撤消,只是把其当做删除数据的日志记录的话,估计只能自己实现一个对应的软删除方法了。
@terranc 嗯,我也这么考量过,例如一般的订单记录表是不可被删除的,直接设置唯一约束,可以不应软删除功能。
所以如果Laravel 内没有其他形式的软删除功能,那么 Laravel 内默认的一个规则就是:软删除和唯一约束不能同时使用,否则只能自己改造或者新写软删除功能。