MySQL ondersteunt functioneel belangrijkste onderdelen sinds 8.0.13 .
-
Als uw versie voldoende recent is, kunt u uw index definiëren als:
UNIQUE(`user_id`, `test_id`, (IFNULL(`completed_date`, -1)))
Merk op dat de bovenstaande index ook dubbele datums voor voltooide uitvoeringen zal voorkomen. Als die geldig zouden zijn, zou een licht gewijzigde index werken:
UNIQUE(`user_id`, `test_id`, ( CASE WHEN `completed_date` IS NOT NULL THEN NULL ELSE 0 END))
Al begint het dan een beetje vies aan te voelen;)
-
Als je ten minste versie 5.7 . hebt je kunt een (virtuele) gegenereerde kolom gebruiken als tijdelijke oplossing:
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`) );
-
Als je vastzit op 5.6 dan een combinatie van een gewone (niet-virtuele) kolom en een licht gewijzigde
INSERT
uitspraken zouden werken: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`) );
In dit geval zou u
is_open
. instellen naartrue
voor onvolledige uitvoeringen en naarNULL
na voltooiing, gebruikmakend van het feit dat tweeNULL
s worden als ongelijk behandeld.