Come posso specificare un vincolo univoco per più colonne in MySQL?


865

Ho un tavolo:

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

Ora voglio rendere le colonne utente, e-mail, indirizzo univoco (insieme).

Come posso farlo in MySql?

Ovviamente l'esempio è solo ... un esempio. Quindi, per favore, non preoccuparti della semantica.

Risposte:


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

31
Funzionerebbe correttamente con la clausola ON DUPLICATE KEY delle istruzioni INSERT? Cioè, se stessi cercando di inserire una riga in conflitto con i valori utente / e-mail / indirizzo di un'altra riga, INSERT eseguirà invece le azioni specificate dalla clausola ON DUPLICATE KEY?
Clizzin,

6
In questo modo la combinazione di tre sarebbe unica? O tutte e tre le singole colonne sarebbero uniche?
Gary Lindahl,

95
Per coloro che usano il workbench di MySQL: vai alla scheda Indexes e seleziona UNIQUE come tipo. Dai un nome al tuo indice e controlla le colonne appropriate nella sezione "Colonne dell'indice"
Pakman,

10
Come me, se qualcun altro lo avesse trovato dai motori di ricerca ... e per rispondere alla domanda di Clizzin sul fatto che ON DUPLICATE KEY funzionerà con una chiave composita - lo farà assolutamente, tuttavia richiederà alcune piccole modifiche alla sintassi. vedi stackoverflow.com/questions/9537710/…
Joe

2
come farlo funzionare anche con valore NULL. Se inseriamo due stesse righe con valore NULL, questo non funziona ...
Wasim A.

237

Ho una tabella 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`)
);

e UNIQUE KEY funziona esattamente come previsto, consente più righe NULL di id_box_elements e id_router.

Sto eseguendo MySQL 5.1.42, quindi probabilmente c'è stato qualche aggiornamento sulla questione discussa sopra. Fortunatamente funziona e speriamo che rimanga tale.


34
Volevo contrassegnare questa risposta in quanto ti mostra come creare una nuova tabella con un indice univoco in cui la risposta di jonstjohn sopra ti dice come aggiornare una tabella esistente. Fanno la stessa cosa anche se dipende solo dalla creazione di una nuova tabella o dall'aggiornamento di una esistente. :)
GazB,

3
che succede con tutti i backquotes, servono a qualche scopo?
puk

8
Viene emesso da Adminer (www.adminer.org) che inserisce automaticamente questi backquotes, quindi non vi è alcun problema con la collisione di parole chiave mysql utilizzate come nomi di colonna.
Frodik,

50

Gli indici univoci a più colonne non funzionano in MySQL se si dispone di un valore NULL in riga poiché MySQL tratta NULL come un valore univoco e almeno attualmente non ha alcuna logica per aggirarlo negli indici a più colonne. Sì, il comportamento è folle, perché limita molte applicazioni legittime di indici multi-colonna, ma è quello che è ... Al momento, è un bug che è stato contrassegnato con "non risolverà" su MySQL bug-track ...


11
Due punti di chiarimento: 1) questo comportamento non ENGINE BDBvale, e, 2) questo è un comportamento documentato , sebbene, IMHO, non sia abbastanza apertamente documentato dato quanto possa essere sorprendente / spiacevole. Vedi un bug di MySQL 25544 bugs.mysql.com/bug.php?id=25544 per una discussione.
Pilcrow

2
Grazie per l'heads NULL, risolto il problema che stavo avendo ... Penso che andrò con un checksum hash
Daniel Doezema,

7
Questa non è una risposta Dovrebbe essere un commento alla domanda originale.
Espiazione limitata il

Documenti ufficiali dicono: Nota che, a partire da MySQL 5.1, BDB non è più supportato.
George

2
Un'ottima informazione, ma non una risposta. È solo perifericamente correlato alla domanda.
Billynoah,

23

Hai provato questo?

UNIQUE KEY `thekey` (`user`,`email`,`address`)

Quello che ha detto Erick funziona bene per me: UNIQUE KEY thekey` ( user, email, address) `. Sto usando MYSQL versione 5.5.24 Puoi impostarlo anche in PHPMYADMIN se lo stai usando. Sto usando la versione 3.5.1 di PMA.
WQC,

Ho provato con MySql 5.6. Funziona dal primo tentativo. Grazie Erick!
Lawrence,

11

Questo funziona con mysql versione 5.5.32

ALTER TABLE  `tablename` ADD UNIQUE (`column1` ,`column2`);

1
Sembra funzionare senza le virgolette singole sul nome della colonna.
Pratik Singhal,

7

MySql 5 o versioni successive si comporta in questo modo (ho appena testato):

  • puoi definire vincoli univoci che coinvolgono colonne nullable. Supponi di definire un vincolo univoco (A, B) in cui A non è nullable ma B lo è
  • quando si valuta un tale vincolo si può avere (A, null) quante volte si desidera (stesso valore A!)
  • puoi avere solo una coppia (A, non nulla B)

Esempio: PRODUCT_NAME, PRODUCT_VERSION 'bicchiere', null 'bicchiere', null 'vino', 1

Ora, se si tenta di inserire nuovamente ('wine' 1), verrà segnalata una violazione del vincolo. Spero che questo aiuti


grazie per aver spiegato. Ho univoco (A, B, C) e non sapevo perché permettesse combinazioni di null con le stesse opzioni non null
Alexandru Topală

6

È possibile aggiungere indici univoci a più colonne tramite phpMyAdmin . (Ho testato nella versione 4.0.4)

Passa alla pagina della struttura per la tabella di destinazione. Aggiungi un indice univoco a una delle colonne. Espandi l' elenco degli indici nella parte inferiore della pagina della struttura per visualizzare l'indice univoco appena aggiunto. Fai clic sull'icona di modifica e nella finestra di dialogo seguente puoi aggiungere colonne aggiuntive a quell'indice univoco.


3

Lo faccio così:

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

La mia convenzione per un unico index_nameè TableName_Column1_Column2_Column3_uindex.


2

Per aggiungere un indice univoco sono richiesti:

1) table_name
2) index_name
3) colonne su cui si desidera aggiungere l'indice

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

Nel tuo caso possiamo creare un indice univoco come segue:

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

1

Se vuoi evitare duplicati in futuro. Crea un'altra colonna dire id2.

UPDATE tablename SET id2 = id;

Ora aggiungi l'esclusivo su due colonne:

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

1

Se stai creando una tabella in mysql, utilizza quanto segue:

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)
);

0

Per prima cosa sbarazzati dei duplicati esistenti

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;

Quindi aggiungere il vincolo univoco

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

Verificare il vincolo con

SHOW CREATE TABLE votes;

Nota che l'utente, l'e-mail e l'indirizzo saranno considerati unici se qualcuno di essi ha un valore nullo al suo interno.


0

Per PostgreSQL ... Non ha funzionato per me con indice; mi ha dato un errore, quindi ho fatto questo:

alter table table_name
add unique(column_name_1,column_name_2);

PostgreSQL ha dato il proprio nome all'indice univoco. Suppongo che puoi cambiare il nome dell'indice nelle opzioni per la tabella, se è necessario cambiarlo ...

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.