it-swarm.com.de

MySQL - eindeutiger Index mit Nullen - tatsächliche Lösung jemand?

CREATE TABLE IF NOT EXISTS b2c_constants (
    id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(64) NOT NULL,
    is_deleted BOOL DEFAULT FALSE,
    UNIQUE (name)
) ENGINE InnoDB CHARSET utf8 COLLATE utf8_unicode_ci

CREATE TABLE IF NOT EXISTS b2c_constant_bindings (
    constant_id INT UNSIGNED NOT NULL,
    company_id INT UNSIGNED NOT NULL,
    object_id INT UNSIGNED DEFAULT NULL,
    property_id INT UNSIGNED DEFAULT NULL,
    value VARCHAR(255) NOT NULL,
    UNIQUE (constant_id, company_id, object_id, property_id),
    FOREIGN KEY (constant_id) REFERENCES b2c_constants (id) ON UPDATE RESTRICT ON DELETE CASCADE,
    FOREIGN KEY (company_id) REFERENCES companies (id) ON UPDATE RESTRICT ON DELETE CASCADE,
    FOREIGN KEY (object_id) REFERENCES b2b_objects (id) ON UPDATE RESTRICT ON DELETE CASCADE,
    FOREIGN KEY (property_id) REFERENCES b2b_properties (id) ON UPDATE RESTRICT ON DELETE CASCADE
) ENGINE InnoDB CHARSET utf8 COLLATE utf8_unicode_ci

Das Problem liegt beim eindeutigen Schlüssel in der Tabelle bindings. Wenn ich Daten habe wie:

constant_id   company_id   object_id   property_id   value
1             1            null        null          foo
1             1            1           null          bar
1             1            1           1             baz

Sie können die ersten beiden Zeilen ohne Fehler unendlich duplizieren, was offensichtlich nicht wünschenswert ist.

Die Idee mit dieser Struktur ist es, Konstanten global pro Unternehmen, pro Objekt im Unternehmen und pro Eigenschaft im Unternehmen zu binden, aber nur eindeutige Konstanten für jede dieser Konstanten zuzulassen.

Gibt es eine Möglichkeit, dies in der Datenbank zu lösen, während die Fremdschlüssel und eine einfache Tabellenstruktur beibehalten werden? Ich weiß, dass ich type ENUM ('company', 'object', 'property'), type_id INT tun könnte, aber damit verliere ich die Fremdschlüssel sowie die erforderliche Firmen-ID für alle Konstanten.

7
jurchiks

[Dies wird nicht getestet, da MySQL 5.7.6 oder höher erforderlich ist]

Obwohl ich den obigen Kommentaren zustimme, habe ich immer noch eine Idee, die ausprobiert werden kann. Ich denke, sie ist nicht die beste in Bezug auf die Leistung, aber sie löst das Problem, das Sie beschreiben.

Die Idee ist, einen Schlüssel hinzuzufügen, der NULL als konkreten Wert wie '0' oder einen anderen Wert behandelt. Indizieren Sie dann die Kombination der Felder, die eindeutig sein sollen, eindeutig.

MySQL 5.7.6 unterstützt generierte Spalten .

ALTER TABLE b2c_constant_bindings
ADD unique_md5 char(32) AS 
    (MD5(CONCAT_WS('X', ifnull(constant_id, 0), ifnull(company_id, 0), ifnull(object_id, 0), ifnull(property_id,0)))) 
    UNIQUE;

Anstatt CONCAT zu verwenden, verwende ich CONCAT_WS, Um zu vermeiden, dass in ähnlichen Fällen wie CONCAT(1, 23) und CONCAT(12, 3) (ss per @Rick James 'dieselben Ergebnisse erzielt werden. beachten).

8
Jehad Keriaki