MySQL stöder funktionella nyckeldelar sedan 8.0.13 .
-
Om din version är tillräckligt ny kan du definiera ditt index som:
UNIQUE(`user_id`, `test_id`, (IFNULL(`completed_date`, -1)))
Observera att ovanstående index också förhindrar dubbla datum för slutförda körningar. Om de skulle vara giltiga skulle ett något modifierat index fungera:
UNIQUE(`user_id`, `test_id`, ( CASE WHEN `completed_date` IS NOT NULL THEN NULL ELSE 0 END))
Fast då börjar det kännas lite smutsigt;)
-
Om du har minst version 5.7 du kan använda en (virtuell) genererad kolumn som lösning:
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`) );
-
Om du har fastnat på 5.6 sedan en kombination av en vanlig (icke-virtuell) kolumn och något modifierad
INSERT
uttalanden skulle fungera: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`) );
I det här fallet skulle du ställa in
is_open
tilltrue
för ofullständiga körningar och tillNULL
efter slutförandet, genom att använda det faktum att tvåNULL
s behandlas som inte lika.