EL CHECK CONSTRAINT EN MYSQL: CÓMO GARANTIZAR LA INTEGRIDAD DE LOS DATOS

El constraint , o restricción de comprobación, es uno de los mecanismos más poderosos de integridad de datos en SQL. Permite definir una condición que debe cumplirse cada vez que se inserta o actualiza una fila en una tabla. Si la condición no se cumple, MySQL rechaza la operación y devuelve un error. A diferencia de restricciones como NOT NULL, UNIQUE, PRIMARY KEY o FOREIGN KEY. CHECK es mucho más flexible porque permite expresiones booleanas complejas que involucran una o varias columnas.

Sintaxis

  1. A nivel de columna:

    columna TIPO_DATO [CONSTRAINT nombre] CHECK (condición)
    
  2. A nivel de tabla (después de definir todas las columnas):

    [CONSTRAINT nombre_constraint] CHECK (condición)
    //También se puede indicar si la restricción está enforced (aplicada) o no:
    CHECK (condición) [NOT] ENFORCED
    

Ejemplos prácticos

  1. CHECK simple a nivel de columna:

    CREATE TABLE empleados (
    id INT PRIMARY KEY AUTO_INCREMENT,
    nombre VARCHAR(100) NOT NULL,
    edad INT CHECK (edad >= 18), -- Debe ser mayor o igual a 18
    salario DECIMAL(10,2) CHECK (salario > 0), -- Salario positivo
    estado_civil ENUM('soltero', 'casado', 'viudo') 
    );
    
  2. CHECK a nivel de tabla con nombre (recomendado):

    CREATE TABLE productos (
    id INT PRIMARY KEY AUTO_INCREMENT,
    nombre VARCHAR(150) NOT NULL,
    precio DECIMAL(10,2) NOT NULL,
    stock INT NOT NULL DEFAULT 0,
    descuento DECIMAL(5,2) DEFAULT 0.00,
    
    CONSTRAINT chk_precio_positivo CHECK (precio > 0),
    CONSTRAINT chk_stock_no_negativo CHECK (stock >= 0),
    CONSTRAINT chk_descuento_valido CHECK (descuento >= 0 AND descuento <= precio * 0.8),
    CONSTRAINT chk_precio_mayor_descuento CHECK (precio > descuento)
    );
    
  3. CHECK complejo con múltiples columnas y lógica condicional: Este es uno de los usos más potentes del CHECK.

    CREATE TABLE pedidos (
    id INT PRIMARY KEY AUTO_INCREMENT,
    tipo ENUM('normal', 'express', 'urgente') NOT NULL,
    fecha_entrega DATE NOT NULL,
    costo_envio DECIMAL(8,2) DEFAULT 0.00,
    
    CONSTRAINT chk_fecha_entrega CHECK (
    (tipo = 'normal' AND fecha_entrega >= DATE_ADD(CURRENT_DATE, INTERVAL 3 DAY)) OR
    (tipo = 'express' AND fecha_entrega >= DATE_ADD(CURRENT_DATE, INTERVAL 1 DAY)) OR
    (tipo = 'urgente' AND fecha_entrega >= CURRENT_DATE)
    ),
    
    CONSTRAINT chk_costo_envio CHECK (
    (tipo = 'normal' AND costo_envio = 0) OR
    (tipo IN ('express', 'urgente') AND costo_envio > 0)
    )
    );
    
  4. Añadir un CHECK a una tabla existente:

    ALTER TABLE empleados 
    ADD CONSTRAINT chk_edad_adulta 
    CHECK (edad >= 18 AND edad <= 70);
    
  5. Desactivar temporalmente una restricción (útil en migraciones):

    ALTER TABLE empleados 
    ALTER CHECK chk_edad_adulta NOT ENFORCED;
    
    -- ... realizar operaciones masivas ...
    
    ALTER TABLE empleados 
    ALTER CHECK chk_edad_adulta ENFORCED;
    
    Atención: Cuando se vuelve a activar "ENFORCED", MySQL no valida los datos existentes automáticamente. Si se quiere validar todo, es mejor eliminar y volver a crear la restricción.
  6. Cómo ver las restricciones CHECK existentes:

    //Para ejecutar esta query hay que tener permisos para usar la bbdd "information_schema"
    -- Ver todas las CHECK constraints del esquema actual
    SELECT * 
    FROM information_schema.CHECK_CONSTRAINTS 
    WHERE CONSTRAINT_SCHEMA = DATABASE();
    -- Ver la definición de una tabla con sus constraints
    SHOW CREATE TABLE empleados;
    
  7. Cómo eliminar un CHECK constraint:

    ALTER TABLE empleados 
    DROP CHECK chk_edad_adulta;
    

Limitaciones importantes del CHECK en MySQL

  • No permite subconsultas (SELECT ... dentro del CHECK).
  • No puede referenciar columnas de otras tablas.
  • No puede usar funciones no determinísticas (como RAND(), NOW() en algunos contextos) ni variables de usuario.
  • No puede referenciar columnas AUTO_INCREMENT.
  • Las expresiones deben ser booleanas (evaluar a TRUE o UNKNOWN). Si evalúa a FALSE, se rechaza la operación.

Ventajas de usar CHECK constraints

  • La validación se realiza en el servidor, independientemente de la aplicación que acceda a la base de datos.
  • Reduce errores de datos corruptos.
  • Mejora la documentación del esquema (las reglas de negocio quedan visibles en la DDL).
  • Aumenta la portabilidad del modelo de datos hacia otros motores SQL.