MySQL podporuje funkční klíčové části od 8.0.13 .
-
Pokud je vaše verze dostatečně aktuální, můžete svůj index definovat jako:
UNIQUE(`user_id`, `test_id`, (IFNULL(`completed_date`, -1)))
Všimněte si, že výše uvedený index také zabrání duplicitním datům pro dokončená provedení. Pokud by měly být platné, fungoval by mírně upravený index:
UNIQUE(`user_id`, `test_id`, ( CASE WHEN `completed_date` IS NOT NULL THEN NULL ELSE 0 END))
I když pak to začíná být trochu špinavé;)
-
Pokud máte alespoň verzi 5.7 můžete použít (virtuální) vygenerovaný sloupec jako řešení:
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`) );
-
Pokud jste uvízli na 5.6 pak kombinace běžného (nevirtuálního) sloupce a mírně upraveného
INSERT
příkazy by fungovaly: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`) );
V tomto případě byste nastavili
is_open
true
pro nedokončená provedení a naNULL
po dokončení s využitím skutečnosti, že dvaNULL
s jsou považovány za nerovné.