Neben der netten Trigger-Lösung von @Rolando gibt es in MySQL eine weitere Problemumgehung (bis CHECKEinschränkungen implementiert sind).
So emulieren Sie einige CHECKEinschränkungen in MySQL
Wenn Sie also referenzielle Integritätsbeschränkungen bevorzugen und Trigger vermeiden möchten (aufgrund der Probleme in MySQL, wenn Sie beide in Ihren Tabellen haben), können Sie eine andere kleine Referenztabelle verwenden:
CREATE TABLE age_allowed
( age TINYINT UNSIGNED NOT NULL
, PRIMARY KEY (age)
) ENGINE = InnoDB ;
Fülle es mit 20 Zeilen:
INSERT INTO age_allowed
(age)
VALUES
(0), (1), (2), (3), ..., (19) ;
Dann wäre Ihr Tisch:
CREATE TABLE test
( id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT
, age TINYINT UNSIGNED NOT NULL
, PRIMARY KEY (id)
, CONSTRAINT age_allowed__in__test
FOREIGN KEY (age)
REFERENCES age_allowed (age)
) ENGINE = InnoDB ;
Sie müssen den Schreibzugriff auf die age_allowedTabelle entfernen, um ein versehentliches Hinzufügen oder Entfernen von Zeilen zu vermeiden.
Dieser Trick funktioniert FLOATleider nicht mit Datentypspalten (zu viele Werte zwischen 0.0und 20.0).
Wie man willkürliche CHECKEinschränkungen in MySQL (5.7) und MariaDB (von 5.2 bis 10.1) emuliert
Da MariaDB hinzugefügt berechnete Spalten in ihrer Version 5.2 (GA - Version: 2010-11-10 ) und MySQL in 5.7 (GA - Version: 2015.10.21 ) - was sie sie nennen VIRTUALund GENERATEDjeweils - , die beibehalten werden können, dh in dem gespeicherte Tisch - sie nennen sie PERSISTENTund STOREDjeweils - wir können sie die obige Lösung zu vereinfachen , verwenden und noch besser, erweitern sie zu emulieren / willkürliche Durchsetzung CHECKEinschränkungen ):
Wie oben benötigen wir eine Hilfetabelle, diesmal jedoch mit einer einzelnen Zeile, die als "Ankertabelle" fungiert. Noch besser ist, dass diese Tabelle für eine beliebige Anzahl von verwendet werden kannCHECK Einschränkungen verwendet werden kann.
Wir fügen dann eine berechnete Spalte , dass auswertet , um entweder TRUE/ FALSE/ UNKNOWN, genau wie ein CHECKZwang würde - aber diese Spalte hat eineFOREIGN KEY Einschränkung unserer Ankertabelle. Wenn die Bedingung / Spalte FALSEfür einige Zeilen mit " 0" bewertet wird , werden die Zeilen aufgrund der FK zurückgewiesen.
Wenn die Bedingung / Spalte als TRUEoder UNKNOWN( NULL) ausgewertet wird , werden die Zeilen nicht genau so abgelehnt, wie es mit CHECKEinschränkungen geschehen sollte :
CREATE TABLE truth
( t BIT NOT NULL,
PRIMARY KEY (t)
) ENGINE = InnoDB ;
-- Put a single row:
INSERT INTO truth (t)
VALUES (TRUE) ;
-- Then your table would be:
-- (notice the change to `FLOAT`, to prove that we don't need)
-- (to restrict the solution to a small type)
CREATE TABLE test
( id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
age FLOAT NOT NULL,
age_is_allowed BIT -- GENERATED ALWAYS
AS (age >= 0 AND age < 20) -- our CHECK constraint
STORED,
PRIMARY KEY (id),
CONSTRAINT check_age_must_be_non_negative_and_less_than_20
FOREIGN KEY (age_is_allowed)
REFERENCES truth (t)
) ENGINE = InnoDB ;
Das Beispiel ist für die MySQL 5.7-Version. In MariaDB (Versionen 5.2+ bis 10.1), wir müssen nur die Syntax ändern und erklären , die Spalte als PERSISTENTstattSTORED . In Version 10.2 wurde das STOREDSchlüsselwort ebenfalls hinzugefügt, sodass das obige Beispiel in beiden Varianten (MySQL und MariaDB) für die neuesten Versionen funktioniert.
Wenn wir viele CHECKEinschränkungen erzwingen möchten (was in vielen Entwürfen üblich ist), müssen wir nur eine berechnete Spalte und einen Fremdschlüssel für jeden von ihnen hinzufügen. Wir brauchen nur einentruth Tabelle in der Datenbank. Es sollte eine Zeile eingefügt und dann alle Schreibrechte entfernt werden.
In der neuesten MariaDB müssen wir diese Akrobatik jedoch nicht mehr ausführen, da CHECKEinschränkungen in Version 10.2.1 (Alpha-Release: 2016-Jul-04) implementiert wurden !
Die aktuelle 10.2.2-Version ist noch eine Beta-Version, aber es scheint, dass die Funktion in der ersten stabilen Version der MariaDB 10.2-Serie verfügbar sein wird.