Además de la buena solución de activación de @Rolando, hay otra solución alternativa para este problema en MySQL (hasta CHECK
que se implementen las restricciones).
Cómo emular algunas CHECK
restricciones en MySQL
Por lo tanto, si prefiere restricciones de integridad referencial y desea evitar los desencadenantes (debido a los problemas en MySQL cuando tiene ambos en sus tablas), puede usar otra pequeña tabla de referencia:
CREATE TABLE age_allowed
( age TINYINT UNSIGNED NOT NULL
, PRIMARY KEY (age)
) ENGINE = InnoDB ;
Llénalo con 20 filas:
INSERT INTO age_allowed
(age)
VALUES
(0), (1), (2), (3), ..., (19) ;
Entonces tu mesa sería:
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 ;
Tendrá que eliminar el acceso de escritura a la age_allowed
tabla, para evitar agregar o eliminar accidentalmente filas.
Este truco no funcionará con FLOAT
columnas de tipo de datos, desafortunadamente (demasiados valores entre 0.0
y 20.0
).
Cómo emular CHECK
restricciones arbitrarias en MySQL (5.7) y MariaDB (desde 5.2 hasta 10.1)
Dado que MariaDB agregó columnas calculadas en su versión 5.2 ( versión GA: 2010-11-10 ) y MySQL en 5.7 (versión GA: 2015-10-21 ), que las llaman VIRTUAL
y GENERATED
respectivamente, eso puede ser persistente, es decir, almacenado en el tabla - los llaman PERSISTENT
y STORED
respectivamente - podemos usarlos para simplificar la solución anterior e incluso mejor, extenderla para emular / imponer CHECK
restricciones arbitrarias ):
Como se indicó anteriormente, necesitaremos una tabla de ayuda, pero esta vez con una sola fila que actuará como una tabla "ancla". Aún mejor, esta tabla se puede usar para cualquier cantidad de CHECK
restricciones.
Luego agregamos una columna calculada que evalúa a TRUE
/ FALSE
/ UNKNOWN
, exactamente como lo CHECK
haría una restricción, pero esta columna tiene una FOREIGN KEY
restricción en nuestra tabla de anclaje. Si la condición / columna se evalúa FALSE
para algunas filas, las filas se rechazan, debido a la FK.
Si la condición / columna se evalúa como TRUE
o UNKNOWN
( NULL
), las filas no se rechazan, exactamente como debería suceder con CHECK
restricciones:
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 ;
El ejemplo es para la versión MySQL 5.7. En MariaDB (versiones 5.2+ hasta 10.1), solo necesitamos modificar la sintaxis y declarar la columna como en PERSISTENT
lugar de STORED
. En la versión 10.2 también STORED
se agregó la palabra clave, por lo que el ejemplo anterior funciona en ambos tipos (MySQL y MariaDB) para las últimas versiones.
Si queremos imponer muchas CHECK
restricciones (lo cual es común en muchos diseños), solo tenemos que agregar una columna calculada y una clave foránea para cada una de ellas. Solo necesitamos una truth
tabla en la base de datos. Debe tener una fila insertada y luego todo acceso de escritura eliminado.
Sin embargo, en el último MariaDB, ya no tenemos que realizar todas estas acrobacias, ya que las CHECK
restricciones se han implementado en la versión 10.2.1 (versión alfa: 2016-Jul-04).
La versión actual 10.2.2 sigue siendo una versión beta, pero parece que la característica estará disponible en la primera versión estable de la serie MariaDB 10.2.