Wie gebe ich eine eindeutige Einschränkung für mehrere Spalten in MySQL an?


865

Ich habe einen Tisch:

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

Jetzt möchte ich die Spalten Benutzer, E-Mail, Adresse eindeutig (zusammen) machen.

Wie mache ich das in MySql?

Natürlich ist das Beispiel nur ... ein Beispiel. Machen Sie sich also bitte keine Sorgen um die Semantik.

Antworten:


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

31
Würde dies mit der ON DUPLICATE KEY-Klausel von INSERT-Anweisungen ordnungsgemäß funktionieren? Wenn ich also versuchen würde, eine Zeile einzufügen, die mit den Benutzer- / E-Mail- / Adresswerten einer anderen Zeile in Konflikt steht, würde INSERT stattdessen die in der ON DUPLICATE KEY-Klausel angegebenen Aktionen ausführen?
Clizzin

6
Auf diese Weise wäre eine Kombination von drei einzigartig? Oder wären alle drei einzelnen Spalten eindeutig?
Gary Lindahl

95
Für Benutzer von MySQL Workbench: Gehen Sie zur Registerkarte Indizes und wählen Sie EINZIGARTIG als Ihren Typ. Geben Sie Ihrem Index einen Namen und überprüfen Sie die entsprechenden Spalten im Abschnitt "
Indexspalten

10
Wie ich, wenn jemand anderes dies von Suchmaschinen gefunden hat ... und um Clizzins Frage zu beantworten, ob ON DUPLICATE KEY mit einem zusammengesetzten Schlüssel funktioniert - dies ist absolut der Fall, erfordert jedoch einige geringfügige Anpassungen der Syntax. siehe stackoverflow.com/questions/9537710/…
Joe

2
wie es funktioniert, auch mit NULL-Wert. Wenn wir zwei gleiche Zeilen mit dem Wert NULL einfügen, funktioniert dies nicht ...
Wasim A.

237

Ich habe eine MySQL-Tabelle:

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

und der EINZIGARTIGE SCHLÜSSEL funktioniert wie erwartet, er erlaubt mehrere NULL-Zeilen von id_box_elements und id_router.

Ich verwende MySQL 5.1.42, daher gab es wahrscheinlich ein Update zu dem oben diskutierten Problem. Zum Glück funktioniert es und hoffentlich bleibt es auch so.


34
Ich wollte diese Antwort markieren, da sie Ihnen zeigt, wie Sie eine neue Tabelle mit einem eindeutigen Index erstellen. In der obigen Antwort von jonstjohn erfahren Sie, wie Sie eine vorhandene Tabelle aktualisieren. Sie tun dasselbe, hängen jedoch nur davon ab, ob Sie eine neue Tabelle erstellen oder eine vorhandene aktualisieren. :)
GazB

3
Was ist mit all den Backquotes? Haben sie einen Zweck?
Puk

8
Es wird von Adminer (www.adminer.org) ausgegeben, das diese Backquotes automatisch einfügt, sodass es kein Problem gibt, MySQL-Schlüsselwörter zu kollidieren, die als Spaltennamen verwendet werden.
Frodik

50

Mehrspaltige eindeutige Indizes funktionieren in MySQL nicht, wenn Sie einen NULL-Wert in der Zeile haben, da MySQL NULL als eindeutigen Wert behandelt und zumindest derzeit keine Logik hat, um ihn in mehrspaltigen Indizes zu umgehen. Ja, das Verhalten ist verrückt, weil es viele legitime Anwendungen von mehrspaltigen Indizes einschränkt, aber es ist das, was es ist ... Bis jetzt ist es ein Fehler, der mit "wird nicht behoben" auf MySQL gestempelt wurde Bug-Track ...


11
Zwei Punkte der Klarstellung: 1) Dieses Verhalten gilt nicht ENGINE BDBund 2) Dies ist ein dokumentiertes Verhalten, obwohl es meiner Meinung nach nicht offen genug dokumentiert ist, da es überraschend / unangenehm sein kann. Eine Diskussion finden Sie unter MySQL-Fehler 25544 bugs.mysql.com/bug.php?id=25544 .
Pilcrow

2
Vielen Dank für die NULL Heads-Ups, die das Problem angesprochen haben, das ich hatte ... Ich denke, ich werde mit einer Hash-Prüfsumme gehen
Daniel Doezema

7
Dies ist keine Antwort. Es sollte ein Kommentar zur ursprünglichen Frage sein.
Begrenzte Versöhnung

Offizielle Dokumente sagen: Beachten Sie, dass BDB ab MySQL 5.1 nicht mehr unterstützt wird.
George D.

2
Sehr gute Informationen, aber keine Antwort. Ist nur peripher mit der Frage verbunden.
Billynoah

23

Hast du das versucht?

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

Was Erick sagte funktioniert bei mir ganz gut: UNIQUE KEY thekey` ( user, email, address) `. Ich verwende MYSQL Version 5.5.24. Sie können dies sogar in PHPMYADMIN einstellen, wenn Sie es verwenden. Ich verwende die 3.5.1-Version von PMA.
WQC

Versuchte es mit MySql 5.6. Funktioniert vom ersten Versuch an. Danke Erick!
Lawrence

11

Dies funktioniert für MySQL Version 5.5.32

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

1
Es scheint ohne die einfachen Anführungszeichen im Spaltennamen zu funktionieren.
Pratik Singhal

7

MySql 5 oder höher verhält sich so (ich habe es gerade getestet):

  • Sie können eindeutige Einschränkungen für nullfähige Spalten definieren. Angenommen, Sie definieren eine eindeutige Einschränkung (A, B), bei der A nicht nullbar ist, B jedoch
  • Wenn Sie eine solche Einschränkung auswerten, können Sie (A, null) so oft haben, wie Sie möchten (gleicher A-Wert!)
  • Sie können nur ein Paar (A, nicht null B) haben

Beispiel: PRODUCT_NAME, PRODUCT_VERSION 'Glas', null 'Glas', null 'Wein', 1

Wenn Sie nun erneut versuchen, ('Wein' 1) einzufügen, wird eine Einschränkungsverletzung gemeldet. Ich hoffe, dies hilft


Danke für die Erklärung. Ich habe ein Unikat (A, B, C) und wusste nicht, warum es Kombinationen von Null mit denselben Nicht-Null-Optionen erlaubt
Alexandru Topală

6

Sie können über phpMyAdmin mehrspaltige eindeutige Indizes hinzufügen . (Ich habe in Version 4.0.4 getestet)

Navigieren Sie zur Strukturseite für Ihre Zieltabelle. Fügen Sie einer der Spalten einen eindeutigen Index hinzu. Erweitern Sie die Liste " Indizes" unten auf der Strukturseite, um den soeben hinzugefügten eindeutigen Index anzuzeigen. Klicken Sie auf das Bearbeitungssymbol. Im folgenden Dialogfeld können Sie diesem eindeutigen Index zusätzliche Spalten hinzufügen.


3

So mach ich es:

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

Meine Konvention für ein einzigartiges index_nameist TableName_Column1_Column2_Column3_uindex.


2

Zum Hinzufügen eines eindeutigen Index sind folgende Elemente erforderlich:

1) Tabellenname
2) Indexname
3) Spalten, für die Sie einen Index hinzufügen möchten

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

In Ihrem Fall können wir einen eindeutigen Index wie folgt erstellen:

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

1

Wenn Sie in Zukunft Duplikate vermeiden möchten. Erstellen Sie eine weitere Spalte mit der Bezeichnung id2.

UPDATE tablename SET id2 = id;

Fügen Sie nun das Unikat in zwei Spalten hinzu:

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

1

Wenn Sie eine Tabelle in MySQL erstellen, verwenden Sie Folgendes:

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

Entfernen Sie zuerst vorhandene Duplikate

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;

Fügen Sie dann die eindeutige Einschränkung hinzu

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

Überprüfen Sie die Einschränkung mit

SHOW CREATE TABLE votes;

Beachten Sie, dass Benutzer, E-Mail-Adresse und Adresse als eindeutig betrachtet werden, wenn einer von ihnen den Wert Null hat.


0

Für PostgreSQL ... Bei Index hat es bei mir nicht funktioniert. es gab mir einen Fehler, also tat ich dies:

alter table table_name
add unique(column_name_1,column_name_2);

PostgreSQL gab dem eindeutigen Index einen eigenen Namen. Ich denke, Sie können den Namen des Index in den Optionen für die Tabelle ändern, wenn er geändert werden muss ...

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.