Contenido de esta guía
Qué cambia al añadir una restricción
Una restricción nueva convierte una expectativa en una regla de la base de datos. UNIQUE limita valores repetidos según las reglas de nulabilidad del motor, CHECK valida una condición, FOREIGN KEY exige que cada referencia no nula tenga una clave compatible en la tabla referenciada y PRIMARY KEY identifica cada registro. Una clave foránea no vuelve obligatoria la columna hija por sí sola: para eso necesitas también NOT NULL cuando corresponda.
El cambio no solo afecta a inserciones futuras. El motor debe comprobar las filas existentes, y la operación falla si alguna incumple la nueva regla, salvo opciones específicas como la validación diferida de determinados motores.
Primero diagnostica los datos
SELECT p.id, p.cliente_id
FROM pedidos AS p
LEFT JOIN clientes AS c
ON c.id = p.cliente_id
WHERE c.id IS NULL;Si la primera consulta devuelve filas, corrige o elimina esas referencias antes de añadir la clave foránea. Para una restricción UNIQUE, agrupa por la columna candidata y busca grupos con COUNT(*) > 1.
| Comprobación | Resultado | Interpretación |
|---|---|---|
| Pedidos con cliente inexistente | 0 filas | La relación actual puede validarse |
| Emails no nulos repetidos | 0 grupos | No hay duplicados que bloqueen UNIQUE |
Emails con NULL | 3 filas | La base educativa los admite; la regla exacta de UNIQUE con varios NULL depende del motor |
Atención a NULL y UNIQUE: PostgreSQL y MySQL permiten normalmente varios valores nulos en una clave única; SQL Server trata los NULL como valores repetidos para un índice o restricción UNIQUE normal y solo admite uno. Si en SQL Server necesitas «emails únicos cuando existen» y varios emails desconocidos, utiliza un índice único filtrado sobre email IS NOT NULL. No copies una estrategia de nulabilidad entre motores sin comprobarla.
Un resultado vacío es una puerta de paso, no una garantía absoluta: evita escrituras concurrentes durante la migración o utiliza el mecanismo de despliegue seguro que ofrezca tu motor.
Patrones habituales
ALTER TABLE pedidos
ADD CONSTRAINT fk_pedidos_cliente
FOREIGN KEY (cliente_id)
REFERENCES clientes (id);
ALTER TABLE pedidos
ADD CONSTRAINT chk_pedidos_total
CHECK (total >= 0);Da un nombre explícito a cada restricción. Será más sencillo reconocer el mensaje de error, documentar una migración o eliminar la regla con DROP CONSTRAINT.
No copies esta sintaxis sin verificar el motor. PostgreSQL, MySQL y SQL Server admiten añadir varias clases de restricciones mediante ALTER TABLE, pero las opciones y nombres difieren. SQLite no ofrece una forma general de ADD CONSTRAINT; normalmente exige recrear la tabla con el esquema deseado y copiar los datos.
Errores frecuentes
Añadir la regla antes de limpiar los datos
Una migración puede detenerse a mitad del despliegue porque existen duplicados, valores nulos o referencias huérfanas. Ejecuta consultas de diagnóstico, mide cuántas filas requieren corrección y prepara una reversión.
No confundas la restricción con el índice. Algunos motores crean o necesitan índices para ciertas claves, pero eliminar un índice no siempre elimina la restricción y viceversa.
Comprueba lo aprendido
Valida y añade una regla en dos pasos
La tabla clientes debe impedir emails repetidos, pero admite emails desconocidos. Escribe la consulta de diagnóstico, indica el resultado esperado con los datos del laboratorio y formula la sentencia orientativa que añade uq_clientes_email.
NULL y agrupa por email.uq_clientes_email y actúa sobre una sola columna.Solución razonada
SELECT email, COUNT(*) AS repeticiones
FROM clientes
WHERE email IS NOT NULL
GROUP BY email
HAVING COUNT(*) > 1;
-- PostgreSQL / MySQL: varios NULL son compatibles con la unicidad habitual
ALTER TABLE clientes
ADD CONSTRAINT uq_clientes_email UNIQUE (email);
-- SQL Server: si deben permitirse varios NULL, usa un índice único filtrado
CREATE UNIQUE INDEX uq_clientes_email
ON clientes (email)
WHERE email IS NOT NULL;La consulta devuelve 0 filas en la base educativa, por lo que no hay emails no nulos repetidos. Los tres NULL obligan a pensar en el motor: PostgreSQL y MySQL permiten varios en una restricción única habitual; SQL Server necesita el índice filtrado mostrado si quieres conservar varios valores desconocidos. SQLite no dispone de un ALTER TABLE ... ADD CONSTRAINT general, aunque puede imponer unicidad mediante un índice único y admite índices parciales.
Compatibilidad entre motores
PostgreSQL permite añadir PRIMARY KEY, UNIQUE, FOREIGN KEY y CHECK; la opción NOT VALID se aplica a restricciones FOREIGN KEY y CHECK, no a cualquier regla. MySQL y SQL Server también admiten restricciones mediante ALTER TABLE, con sintaxis y validación propias. En SQL Server, una restricción UNIQUE normal permite un solo NULL por columna; un índice único filtrado permite aplicar la unicidad solo a filas no nulas. SQLite soporta un subconjunto de ALTER TABLE y no una operación general ADD CONSTRAINT. Desde SQLite 3.53.0 puede añadir o quitar NOT NULL y CHECK mediante ALTER COLUMN; otras restricciones siguen requiriendo otra estrategia, como recrear la tabla o utilizar un índice cuando el requisito sea de unicidad.
Qué debes recordar
- Comprueba primero las filas existentes.
- Nombra la restricción de forma explícita.
- Planifica bloqueo, duración y reversión.
- La sintaxis y las capacidades cambian entre motores.