Mysql

僅當列具有特定值時 MySQL 唯一索引

  • March 19, 2017

我有一個表,我在其中使用布爾列deleted來表示特定記錄是否已被使用者“刪除”(意思是,它出現在垃圾列表而不是普通列表中)。這些物品都有應該是獨一無二的蛞蝓。

但是,如果使用者想要添加一個帶有與已刪除記錄的 slug 相同的 slug 的項目,則應該允許它。我嘗試使用 UNIQUE 索引來執行此操作deletedslug但是,如果該項目將被刪除,則會出現問題:垃圾列表中應該有兩個項目具有相同的 slug,這將違反約束。

所以實際上我需要一個僅適用於deleted=0的記錄的約束

我已經看到了自定義唯一列約束的問題,僅當一列具有特定值時才強制執行,但是,它僅適用於 PostgreSQL 並且我在 MySQL 上。MySQL中有沒有辦法做到這一點,或者一個很好的解決方法?

我想製作deleted一個整數而不是布爾值,其中 0 表示not deleted和任何其他數字deleted。然後,具有相同 slug 的已刪除項目在列中可能具有不同的值deleted

但是,這意味著介面軟體(用 PHP 編寫)必須檢查deleted如果發生約束衝突,它可以在列中放入什麼,當然我更喜歡純 MySQL 解決方案。如果無論如何我要在 PHP 程式碼中編寫它,我寧願更改slug值,例如,id在刪除項目時將記錄添加到 slug - 或者,為已刪除的項目創建第二個表記錄,其中不存在此類約束。

無論如何,有沒有一種純粹的 MySQL 方法可以做到這一點?


注意:當然,當使用者請求恢復以前刪除的項目時,當它的 slug 已經分配給新記錄時,這種方案會遇到困難。無論如何,這必須在介面程式碼中完成。

如果您有生成唯一整數的方法,則不必檢查可以在“已刪除”中使用的值,而 MySQL 確實…該函式每次呼叫時都會UUID_SHORT()生成一個唯一且單調的值。BIGINT UNSIGNED

該函式適用於每秒 1670 萬個新值,只要@@SERVER_ID保持不變並且您不關閉伺服器,將系統時鐘向後設置,就永遠不會返回重複的(或小於以前的)值及時,並重新啟動伺服器……即使你這樣做,重複值的機率仍然很小,但不再是真正不可能的。

您還可以在 MySQL 5.6 上將“已刪除”設置為 aDATETIME(6)TIMESTAMP(6),使用 ‘0000-00-00 00:00:00.000000’ 表示“未刪除”並NOW()表示已刪除。

盡我所能,我無法讓 MySQL 產生NOW()精確到微秒的衝突。

引用自:https://dba.stackexchange.com/questions/85966