数据库
首页 > 数据库> > 仅当列具有特定值时,MySQL唯一索引

仅当列具有特定值时,MySQL唯一索引

作者:互联网

我有一个表,我使用删除的布尔列来表示用户是否已“删除”特定记录(意味着它出现在垃圾列表而不是正常列表中).这些物品都有slugs,应该是独一无二的.

但是,如果用户想要添加一个与已删除记录的slug相同的slug的项目,则应该允许它.我尝试使用删除和slug上的UNIQUE索引执行此操作,但是,如果此项目将被删除,则会出现问题:垃圾邮件列表中应该有两个具有相同slug的项目,这将导致约束违规.

所以实际上我需要一个约束,它只适用于删除= 0的记录

我已经看到了问题Custom unique column constraint, only enforced if one column has a specific value,但是,它只适用于PostgreSQL而且我在MySQL上.在MySQL中有没有办法做到这一点,还是一个很好的解决方法?

我想删除一个整数而不是布尔值,其中0表示不删除,任何其他数字删除.然后,具有相同slug的已删除项目在已删除列中可能具有不同的值.

但是,这意味着接口软件(用PHP编写)必须检查在发生约束违规时它可以放入已删除列中的内容,当然我更喜欢纯MySQL解决方案.如果我打算在PHP代码中写这个,我宁愿更改slug值,例如,当项目被删除时,将记录的id添加到slug中 – 或者,创建第二个表已删除的记录,不存在此类约束.

无论如何,有没有一种纯粹的MySQL方式来做到这一点?

注意:当然,当用户请求将其slug已分配给新记录时,请求恢复先前删除的项目时,此类方案将会遇到困难.在任何情况下都必须在接口代码中完成.

解决方法:

如果你有一种生成唯一整数的方法,你不必检查你可以在“删除”中使用什么值,而MySQL确实…… UUID_SHORT()函数每次调用时都会生成一个唯一且单调的BIGINT UNSIGNED值.

该函数适用于每秒16.7M新值,每秒,并且永远不会返回重复(或小于先前)值,只要@@ SERVER_ID保持不变并且您不关闭服务器,设置系统时钟倒退,并重新启动服务器…即使你这样做,重复值的几率仍然非常小,但不再是真正不可能的.

您还可以在MySQL 5.6上将“已删除”设置为DATETIME(6)或TIMESTAMP(6),使用“0000-00-00 00:00:00.000000”表示“未删除”,NOW()表示已删除.

尽我所能,我无法让MySQL产生一个NOW()碰撞到微秒.

标签:unique-index,mysql,constraint
来源: https://codeday.me/bug/20190806/1596935.html