¿Cómo especifico una restricción única para múltiples columnas en MySQL?

865

Tengo una mesa:

table votes (
    id,
    user,
    email,
    address,
    primary key(id),
);

Ahora quiero hacer que las columnas usuario, correo electrónico, dirección sean únicas (juntas).

¿Cómo hago esto en MySql?

Por supuesto, el ejemplo es solo ... un ejemplo. Así que no te preocupes por la semántica.

Niyaz
fuente

Respuestas:

1436
ALTER TABLE `votes` ADD UNIQUE `unique_index`(`user`, `email`, `address`);
jonstjohn
fuente
31
¿Funcionaría esto correctamente con la cláusula ON DUPLICATE KEY de las instrucciones INSERT? Es decir, si intentara insertar una fila que entrara en conflicto con los valores de usuario / correo electrónico / dirección de otra fila, ¿INSERT haría las acciones especificadas en la cláusula ON DUPLICATE KEY?
clizzin
66
De esa manera, la combinación de tres sería única? ¿O todas las tres columnas individuales serían únicas?
Gary Lindahl
95
Para aquellas personas que usan MySQL workbench: vaya a la pestaña Índices y seleccione UNIQUE como su tipo. Dé un nombre a su índice y verifique las columnas apropiadas en la sección "Columnas de índice"
Pakman
10
Al igual que yo, si alguien más encontró esto en los motores de búsqueda ... y para responder a la pregunta de Clizzin sobre si ON DUPLICATE KEY funcionará con una clave compuesta, absolutamente lo hará, sin embargo, requerirá algunos ajustes menores a la sintaxis. ver stackoverflow.com/questions/9537710/…
Joe
2
cómo hacer que funcione incluso con valor NULL. Si insertamos dos mismas filas con valor NULL, esto no está funcionando ...
Wasim A.
237

Tengo una tabla MySQL:

CREATE TABLE `content_html` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `id_box_elements` int(11) DEFAULT NULL,
  `id_router` int(11) DEFAULT NULL,
  `content` mediumtext COLLATE utf8_czech_ci NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `id_box_elements` (`id_box_elements`,`id_router`)
);

y la CLAVE ÚNICA funciona como se esperaba, permite múltiples filas NULAS de id_box_elements e id_router.

Estoy ejecutando MySQL 5.1.42, por lo que probablemente hubo alguna actualización sobre el problema discutido anteriormente. Afortunadamente funciona y espero que siga así.

Frodik
fuente
34
Quería marcar esta respuesta, ya que te muestra cómo crear una nueva tabla con un índice único donde, como la respuesta de jonstjohn anterior, te dice cómo actualizar una tabla existente. Hacen lo mismo, aunque solo depende de si está creando una nueva tabla o actualizando una existente. :)
GazB
3
¿Qué pasa con todos los backquotes, sirven para algún propósito?
puk
8
Se emite desde Adminer (www.adminer.org) que inserta estas comillas inversas automáticamente, por lo que no hay problema con la colisión de palabras clave mysql utilizadas como nombres de columna.
Frodik
50

Los índices únicos de varias columnas no funcionan en MySQL si tiene un valor NULL en fila, ya que MySQL trata a NULL como un valor único y al menos actualmente no tiene lógica para evitarlo en los índices de varias columnas. Sí, el comportamiento es una locura, ya que limita muchas aplicaciones legítimas de índices de varias columnas, pero es lo que es ... Hasta el momento, es un error que se ha marcado con "no se solucionará" en MySQL pista de error ...

niksoft
fuente
11
Dos puntos de aclaración: 1) este comportamiento no es válido ENGINE BDBy, 2) este es un comportamiento documentado , aunque, en mi humilde opinión, no está suficientemente documentado dado lo sorprendente / desagradable que puede ser. Vea el error 25544 bugs.mysql.com/bug.php?id=25544 de MySQL para una discusión.
Pilcrow
2
Gracias por la advertencia NULL, abordé el problema que estaba teniendo ... Creo que iré con una suma de comprobación hash
Daniel Doezema
77
Esta no es una respuesta. Debería ser un comentario a la pregunta original.
Expiación limitada el
Los documentos oficiales dicen: tenga en cuenta que, a partir de MySQL 5.1, BDB ya no es compatible.
George D.
2
Muy buena información, pero no una respuesta. Solo está periféricamente relacionado con la pregunta.
billynoah
23

¿Has probado esto?

UNIQUE KEY `thekey` (`user`,`email`,`address`)
Erick
fuente
Lo dijo Erick funciona muy bien para mí: UNIQUE KEY thekey` ( user, email, address) `. Estoy usando MYSQL versión 5.5.24 Puede configurar esto incluso en PHPMYADMIN si lo está usando. Estoy usando la versión 3.5.1 de PMA.
WQC
Probé con MySql 5.6. Funciona desde el primer intento. Gracias Erick!
Lawrence
11

Esto funciona para mysql versión 5.5.32

ALTER TABLE  `tablename` ADD UNIQUE (`column1` ,`column2`);
rizon
fuente
1
Parece funcionar sin las comillas simples en el nombre de la columna.
Pratik Singhal
7

MySql 5 o superior se comporta así (acabo de probar):

  • puede definir restricciones únicas que involucran columnas anulables. Supongamos que define una restricción única (A, B) donde A no es anulable pero B sí
  • al evaluar dicha restricción, puede tener (A, nulo) tantas veces como desee (¡el mismo valor A!)
  • solo puede tener un par (A, no nulo B)

Ejemplo: PRODUCT_NAME, PRODUCT_VERSION 'vaso', nulo 'vaso', nulo 'vino', 1

Ahora, si intenta insertar ('vino' 1) nuevamente, informará una violación de restricción Espero que esto ayude

Cristian Botiza
fuente
gracias por la explicación. Tengo un único (A, B, C) y no sabía por qué permitía combinaciones de nulo con las mismas opciones no nulas
Alexandru Topală
6

Puede agregar índices únicos de varias columnas a través de phpMyAdmin . (Probé en la versión 4.0.4)

Navegue a la página de estructura para su tabla de destino. Agregue un índice único a una de las columnas. Expanda la lista de Índices en la parte inferior de la página de estructura para ver el índice único que acaba de agregar. Haga clic en el icono de edición y en el siguiente cuadro de diálogo puede agregar columnas adicionales a ese índice único.

Vince K
fuente
3

Lo hago así:

CREATE UNIQUE INDEX index_name ON TableName (Column1, Column2, Column3);

Mi convención para un único index_namees TableName_Column1_Column2_Column3_uindex.

Sam Malayek
fuente
2

Para agregar un índice único se requieren los siguientes:

1) nombre_tabla
2) nombre_índice
3) columnas en las que desea agregar índice

ALTER TABLE  `tablename` 
ADD UNIQUE index-name
(`column1` ,`column2`,`column3`,...,`columnN`);

En su caso, podemos crear un índice único de la siguiente manera:

ALTER TABLE `votes`ADD 
UNIQUE <votesuniqueindex>;(`user` ,`email`,`address`);
sandeep vanama
fuente
1

Si desea evitar duplicados en el futuro. Cree otra columna, diga id2.

UPDATE tablename SET id2 = id;

Ahora agregue el único en dos columnas:

alter table tablename add unique index(columnname, id2);
kumar
fuente
1

Si está creando una tabla en mysql, use lo siguiente:

create table package_template_mapping (
mapping_id  int(10) not null auto_increment  ,
template_id int(10) NOT NULL ,
package_id  int(10) NOT NULL ,
remark      varchar(100),
primary key (mapping_id) ,
UNIQUE KEY template_fun_id (template_id , package_id)
);
Devendra Singraul
fuente
0

Primero deshazte de los duplicados existentes

delete a from votes as a, votes as b where a.id < b.id 
and a.user <=> b.user and a.email <=> b.email 
and a.address <=> b.address;

Luego agregue la restricción única

ALTER TABLE votes ADD UNIQUE unique_index(user, email, address);

Verifique la restricción con

SHOW CREATE TABLE votes;

Tenga en cuenta que el usuario, el correo electrónico y la dirección se considerarán únicos si alguno de ellos tiene un valor nulo.

Ganesh Krishnan
fuente
0

Para PostgreSQL ... No funcionó para mí con index; me dio un error, así que hice esto:

alter table table_name
add unique(column_name_1,column_name_2);

PostgreSQL le dio a índice único su propio nombre. Supongo que puede cambiar el nombre del índice en las opciones de la tabla, si es necesario cambiarlo ...

quinta
fuente