MySQL mendukung fungsional bagian penting sejak 8.0.13 .
-
Jika versi Anda cukup baru, Anda dapat menentukan indeks sebagai:
UNIQUE(`user_id`, `test_id`, (IFNULL(`completed_date`, -1)))
Perhatikan bahwa indeks di atas juga akan mencegah tanggal duplikat untuk eksekusi yang telah selesai. Jika itu harus valid maka indeks yang sedikit dimodifikasi akan berfungsi:
UNIQUE(`user_id`, `test_id`, ( CASE WHEN `completed_date` IS NOT NULL THEN NULL ELSE 0 END))
Meskipun kemudian mulai terasa agak kotor;)
-
Jika Anda memiliki setidaknya versi 5.7 anda dapat menggunakan (virtual) kolom yang dihasilkan sebagai solusinya:
CREATE TABLE `executed_tests` ( `id` INTEGER AUTO_INCREMENT NOT NULL, `user_id` INTEGER NOT NULL, `test_id` INTEGER NOT NULL, `start_date` DATE NOT NULL, `completed_date` DATE, `_helper` CHAR(11) AS (IFNULL(`completed_date`, -1)), PRIMARY KEY (`id`), UNIQUE(`user_id`, `test_id`, `_helper`) );
-
Jika Anda terjebak pada 5.6 kemudian kombinasi kolom biasa (non-virtual) dan
INSERT
. yang sedikit dimodifikasi pernyataan akan berhasil:CREATE TABLE `executed_tests` ( `id` INTEGER AUTO_INCREMENT NOT NULL, `user_id` INTEGER NOT NULL, `test_id` INTEGER NOT NULL, `start_date` DATE NOT NULL, `completed_date` DATE, `is_open` BOOLEAN, PRIMARY KEY (`id`), UNIQUE(`user_id`, `test_id`, `is_open`) );
Dalam hal ini Anda akan mengatur
is_open
untuktrue
untuk eksekusi yang tidak lengkap dan untukNULL
setelah selesai, manfaatkan fakta bahwa duaNULL
s diperlakukan tidak sama.