Contenido de esta guía
Qué garantiza UNIQUE
Una restricción UNIQUE evita que dos filas tengan el mismo valor en la columna o combinación indicada. Es útil para datos como un email de acceso, un código de producto o la pareja formada por alumno y curso.
Una tabla puede tener varias restricciones UNIQUE. En cambio, solo tiene una PRIMARY KEY, que identifica cada fila y además implica ausencia de NULL.
Una columna y una combinación
CREATE TABLE usuarios_demo (
id INTEGER PRIMARY KEY,
email VARCHAR(200) NOT NULL UNIQUE
);
CREATE TABLE inscripciones_demo (
id INTEGER PRIMARY KEY,
alumno_id INTEGER NOT NULL,
curso_id INTEGER NOT NULL,
UNIQUE (alumno_id, curso_id)
);En usuarios_demo, ningún email puede repetirse. En inscripciones_demo, un alumno puede aparecer en varios cursos y un curso puede tener varios alumnos, pero la misma pareja no puede registrarse dos veces.
Ejemplo guiado
INSERT INTO inscripciones_demo (id, alumno_id, curso_id)
VALUES (1, 10, 7);
INSERT INTO inscripciones_demo (id, alumno_id, curso_id)
VALUES (2, 10, 8);
INSERT INTO inscripciones_demo (id, alumno_id, curso_id)
VALUES (3, 10, 7);| Fila | Resultado |
|---|---|
| (10, 7) | Aceptada |
| (10, 8) | Aceptada |
| (10, 7) repetida | Rechazada por UNIQUE |
Qué ocurre con NULL
El tratamiento de NULL dentro de una restricción única no es idéntico en todos los motores. SQLite y PostgreSQL permiten varios NULL por defecto; PostgreSQL también permite pedir NULLS NOT DISTINCT. SQL Server, en cambio, trata NULL como un valor a efectos de una clave única normal, por lo que una columna única nullable admite como máximo un NULL.
Cuando el dato debe existir y además no repetirse, expresa ambas reglas: NOT NULL UNIQUE. No dependas del comportamiento de NULL para definir una identidad.
SELECT email, COUNT(*) AS repeticiones
FROM clientes
WHERE email IS NOT NULL
GROUP BY email
HAVING COUNT(*) > 1;
SELECT COUNT(*) AS emails_desconocidos
FROM clientes
WHERE email IS NULL;| Comprobación | Resultado |
|---|---|
| Emails no nulos repetidos | 0 grupos |
| Emails desconocidos | 3 filas |
La unicidad puede añadirse sin limpiar duplicados no nulos. Sin embargo, si el requisito del dominio dice «cada cliente debe tener email», también necesitas resolver esos tres NULL y declarar NOT NULL.
Error frecuente
Marcar cada columna como UNIQUE por separado
alumno_id INTEGER UNIQUE,
curso_id INTEGER UNIQUEEsta definición permitiría un solo registro por alumno y un solo registro por curso. Para impedir solo la pareja duplicada, declara UNIQUE (alumno_id, curso_id).
Comprueba lo aprendido
Evita repetir una valoración
Una tabla guarda valoraciones de productos. Cada cliente puede valorar muchos productos, pero solo una vez cada producto. Define la regla adecuada sobre cliente_id y producto_id.
Solución razonada
CREATE TABLE valoraciones (
id INTEGER PRIMARY KEY,
cliente_id INTEGER NOT NULL,
producto_id INTEGER NOT NULL,
puntuacion INTEGER NOT NULL,
UNIQUE (cliente_id, producto_id)
);La restricción permite que cada identificador se repita, pero bloquea la pareja duplicada.
En un esquema real añadirías además una restricción para el intervalo de puntuacion, por ejemplo entre 1 y 5. UNIQUE resuelve la repetición de la pareja, no la validez del valor puntuado.
Compatibilidad entre motores
La restricción sobre una o varias columnas está ampliamente soportada, pero el tratamiento de NULL cambia. SQLite considera distintos los valores NULL dentro de UNIQUE. PostgreSQL también los considera distintos por defecto y permite declarar NULLS NOT DISTINCT cuando el dominio necesita aceptar como máximo un nulo. SQL Server admite como máximo un NULL en una columna con una restricción o índice único normal; si necesitas aplicar unicidad solo a valores no nulos, puedes usar un índice único filtrado con una condición IS NOT NULL. La forma de añadir, nombrar o retirar la restricción también depende del motor.
Qué debes recordar
UNIQUEprotege valores o combinaciones que no deben repetirse.- No sustituye automáticamente a una clave primaria.
- Una restricción compuesta actúa sobre la combinación completa.
- Añade
NOT NULLcuando el dato también sea obligatorio.
Si además necesitas comparar dos valores opcionales sin que NULL convierta la igualdad en desconocida, consulta IS DISTINCT FROM.