UNIQUE
La restricción UNIQUE garantiza que todos los valores de una columna (o combinación de columnas) sean distintos. A diferencia de PRIMARY KEY, una tabla puede tener múltiples restricciones UNIQUE, y las columnas UNIQUE permiten valores NULL (aunque con matices). Es la herramienta adecuada para columnas que necesitan ser únicas pero no son la clave primaria, como el email de un usuario o el código de un producto.
Sintaxis
Como restricción de columna:
CREATE TABLE nombre_tabla (
columna tipo_de_dato UNIQUE
);Como restricción de tabla (permite nombrarla):
CREATE TABLE nombre_tabla (
columna tipo_de_dato,
CONSTRAINT nombre_restriccion UNIQUE (columna)
);Ejemplo básico
CREATE TABLE usuarios (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(100) NOT NULL,
email VARCHAR(150) NOT NULL UNIQUE,
telefono VARCHAR(20) UNIQUE
);Las columnas email y telefono no pueden contener valores duplicados:
INSERT INTO usuarios (nombre, email, telefono)
VALUES ('Ana García', 'ana@email.com', '612345678');
INSERT INTO usuarios (nombre, email, telefono)
VALUES ('Luis Martín', 'ana@email.com', '623456789');ERROR 1062 (23000): Duplicate entry 'ana@email.com' for key 'usuarios.email'
El segundo INSERT falla porque el email ya existe.
UNIQUE en tienda_mysql
Nuestra base de datos usa UNIQUE en varias tablas. La más notable es la tabla clientes, donde el email es único:
-- Intentar insertar un cliente con email duplicado
INSERT INTO clientes (nombre, apellidos, email)
VALUES ('Test', 'Prueba', 'maria.garcia@email.com');ERROR 1062 (23000): Duplicate entry 'maria.garcia@email.com' for key 'clientes.email'
La tabla etiquetas_producto tiene un índice UNIQUE compuesto que impide que un producto tenga la misma etiqueta dos veces:
-- El producto 1 ya tiene la etiqueta 'premium'
INSERT INTO etiquetas_producto (producto_id, etiqueta)
VALUES (1, 'premium');ERROR 1062 (23000): Duplicate entry '1-premium' for key 'etiquetas_producto.uk_producto_etiqueta'
UNIQUE y NULL
Las columnas UNIQUE permiten valores NULL. En MySQL, múltiples filas pueden tener NULL en una columna UNIQUE porque NULL no se considera igual a otro NULL:
INSERT INTO usuarios (nombre, email, telefono)
VALUES ('Eva López', 'eva@email.com', NULL);
INSERT INTO usuarios (nombre, email, telefono)
VALUES ('Carlos Ruiz', 'carlos@email.com', NULL);Query OK, 1 row affected (0.01 sec)
Ambas inserciones funcionan aunque telefono es NULL en ambos casos. Esto es diferente de PRIMARY KEY, que no permite NULL en absoluto.
SELECT nombre, email, telefono FROM usuarios;| nombre | telefono | |
|---|---|---|
| Ana García | ana@email.com | 612345678 |
| Eva López | eva@email.com | NULL |
| Carlos Ruiz | carlos@email.com | NULL |
UNIQUE compuesto
Puedes definir una restricción UNIQUE sobre varias columnas. La combinación debe ser única, pero cada columna individual puede repetirse:
CREATE TABLE horarios (
id INT AUTO_INCREMENT PRIMARY KEY,
profesor_id INT NOT NULL,
dia ENUM('lunes', 'martes', 'miercoles', 'jueves', 'viernes') NOT NULL,
hora TIME NOT NULL,
aula VARCHAR(10) NOT NULL,
CONSTRAINT uk_profesor_horario UNIQUE (profesor_id, dia, hora),
CONSTRAINT uk_aula_horario UNIQUE (aula, dia, hora)
);La primera restricción impide que un profesor tenga dos clases al mismo tiempo. La segunda impide que un aula esté ocupada por dos clases simultáneamente. Un profesor puede repetirse (tiene varias clases) y un día puede repetirse (hay muchas clases cada día), pero la combinación profesor-día-hora debe ser única.
INSERT INTO horarios (profesor_id, dia, hora, aula) VALUES
(1, 'lunes', '09:00', 'A101'),
(1, 'lunes', '10:00', 'A101'), -- OK: misma aula, diferente hora
(2, 'lunes', '09:00', 'B202'); -- OK: mismo día y hora, diferente aula
-- ERROR: mismo profesor, mismo día y hora
INSERT INTO horarios (profesor_id, dia, hora, aula) VALUES
(1, 'lunes', '09:00', 'C303');ERROR 1062 (23000): Duplicate entry '1-lunes-09:00:00' for key 'horarios.uk_profesor_horario'
Añadir UNIQUE a tabla existente
ALTER TABLE usuarios
ADD CONSTRAINT uk_nombre UNIQUE (nombre);Si hay valores duplicados en la columna, la operación falla:
ERROR 1062 (23000): Duplicate entry 'valor' for key 'usuarios.uk_nombre'
Primero verifica y resuelve los duplicados:
SELECT nombre, COUNT(*) AS repeticiones
FROM usuarios
GROUP BY nombre
HAVING COUNT(*) > 1;Eliminar restricción UNIQUE
MySQL implementa las restricciones UNIQUE como índices, por lo que se eliminan con DROP INDEX:
ALTER TABLE usuarios
DROP INDEX uk_nombre;También puedes usar el nombre generado automáticamente (normalmente es el nombre de la columna):
ALTER TABLE usuarios
DROP INDEX telefono;UNIQUE vs PRIMARY KEY
Ambas garantizan unicidad, pero hay diferencias importantes:
Una tabla solo puede tener una PRIMARY KEY, pero puede tener múltiples restricciones UNIQUE. PRIMARY KEY no admite NULL; UNIQUE sí los permite. PRIMARY KEY define el índice clustered en InnoDB (los datos se almacenan físicamente ordenados por la clave primaria); UNIQUE crea un índice secundario.
En la práctica, usa PRIMARY KEY para el identificador principal de la tabla (normalmente un id autoincremental) y UNIQUE para otros campos que deben ser únicos (email, código, DNI, etc.).
UNIQUE y rendimiento
MySQL crea automáticamente un índice para cada restricción UNIQUE. Esto tiene dos consecuencias: las búsquedas por columnas UNIQUE son rápidas (usan el índice), pero las inserciones y actualizaciones son ligeramente más lentas (deben verificar la unicidad).
Para ver los índices de una tabla:
SHOW INDEX FROM usuarios;Cada restricción UNIQUE aparece como un índice con Non_unique = 0.
Limpieza
DROP TABLE IF EXISTS horarios;
DROP TABLE IF EXISTS usuarios;En el siguiente artículo veremos la cláusula DEFAULT, que asigna valores automáticos a las columnas.
Escrito por Eduardo Lázaro
