MySQLは
-
バージョンが十分に新しい場合は、インデックスを次のように定義できます。
UNIQUE(`user_id`, `test_id`, (IFNULL(`completed_date`, -1)))
上記のインデックスは、完了した実行の日付の重複を防ぐことにも注意してください。それらが有効である必要がある場合は、わずかに変更されたインデックスが機能します:
UNIQUE(`user_id`, `test_id`, ( CASE WHEN `completed_date` IS NOT NULL THEN NULL ELSE 0 END))
それから少し汚れた感じがしますが;)
-
少なくともバージョン5.7をお持ちの場合 (仮想)生成された列を使用できます 回避策として:
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`) );
-
5.6で立ち往生している場合 次に、通常の(非仮想)列とわずかに変更された
INSERT
の組み合わせ ステートメントは機能します: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`) );
この場合、
is_open
を設定しますtrue
に 不完全な実行およびNULL
完了後、2つのNULL
sは等しくないものとして扱われます。