sql >> Database teknologi >  >> RDS >> Mysql

Indstil kun en unik begrænsning, når et felt er nul

MySQL understøtter funktionelle nøgledele siden 8.0.13 .

  • Hvis din version er tilstrækkelig ny, kan du definere dit indeks som:

    UNIQUE(`user_id`, `test_id`, (IFNULL(`completed_date`, -1)))
    

    (Demo på dbfiddle.uk )

    Bemærk, at ovenstående indeks også vil forhindre duplikerede datoer for afsluttede henrettelser. Hvis disse skulle være gyldige, ville et let ændret indeks fungere:

    UNIQUE(`user_id`, `test_id`, (
        CASE WHEN `completed_date` IS NOT NULL
        THEN NULL
        ELSE 0
    END))
    

    (Demo på dbfiddle.uk )

    Selvom det så begynder at føles lidt beskidt;)

  • Hvis du mindst har version 5.7 du kan bruge en (virtuel) genereret kolonne som en 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`)
    );
    

    (Demo på dbfiddle.uk )

  • Hvis du sidder fast på 5.6 derefter en kombination af en almindelig (ikke-virtuel) kolonne og let ændret INSERT udsagn ville fungere:

    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 dette tilfælde ville du indstille is_open til true for ufuldstændige eksekveringer og til NULL efter afslutning, ved at bruge det faktum, at to NULL s behandles som ulige.

    (Demo på dbfiddle.uk )




  1. Optimering af MySQL-forespørgsler:Er det altid muligt at optimere en forespørgsel, så den ikke bruger ALLE

  2. Brug af udefineret konstant DB_USER - antaget 'DB_USER'

  3. SQL-problem:Brug af CONTAINS() virker ikke, men LIKE fungerer fint

  4. MySQL vælger hurtigt 10 tilfældige rækker fra 600.000 rækker