MySQL prend en charge fonctionnel éléments clés depuis 8.0.13 .
-
Si votre version est suffisamment récente, vous pouvez définir votre index comme :
UNIQUE(`user_id`, `test_id`, (IFNULL(`completed_date`, -1)))
Notez que l'index ci-dessus empêchera également les dates en double pour les exécutions terminées. Si ceux-ci devaient être valides, un index légèrement modifié fonctionnerait :
UNIQUE(`user_id`, `test_id`, ( CASE WHEN `completed_date` IS NOT NULL THEN NULL ELSE 0 END))
Même si ça commence à être un peu sale;)
-
Si vous avez au moins la version 5.7 vous pouvez utiliser une colonne générée (virtuelle) comme solution de contournement :
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`) );
-
Si vous êtes bloqué sur 5.6 puis une combinaison d'une colonne normale (non virtuelle) et de
INSERT
légèrement modifié les instructions fonctionneraient :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`) );
Dans ce cas, vous définiriez
is_open
àtrue
pour les exécutions incomplètes et àNULL
après l'achèvement, en utilisant le fait que deuxNULL
s sont traités comme non égaux.