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
INSERTuttalanden 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_opentilltrueför ofullständiga körningar och tillNULLefter slutförandet, genom att använda det faktum att tvåNULLs behandlas som inte lika.