如何在MySQL中为多个列指定唯一约束?


864

我有一张桌子:

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

现在,我想使列的用户,电子邮件,地址唯一(在一起)。

如何在MySql中执行此操作?

当然,这个例子仅仅是……一个例子。因此,请不要担心语义。

Answers:


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

31
这可以与INSERT语句的ON DUPLICATE KEY子句一起正常工作吗?也就是说,如果我试图插入与另一行的用户/电子邮件/地址值冲突的行,那么INSERT会执行ON DUPLICATE KEY子句指定的操作吗?
clizzin

6
这样三者的结合将是独特的?还是所有三列都是唯一的?
Gary Lindahl

95
对于使用MySQL工作台的人员:转到索引选项卡,然后选择UNIQUE作为您的类型。给您的索引
起个名字,

10
像我一样,如果有人从搜索引擎中发现此问题……并回答Clizzin有关ON DUPLICATE KEY是否可以与复合键一起使用的问题-绝对可以,但是需要对语法进行一些小的调整。参见stackoverflow.com/questions/9537710/…–

2
如何使它即使使用NULL值也能工作。如果我们插入两个具有NULL值的相同行,则该行不起作用...
Wasim A.

237

我有一个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`)
);

并且UNIQUE KEY可以按预期工作,它允许id_box_elements和id_router的多个NULL行。

我正在运行MySQL 5.1.42,因此上面讨论的问题可能有一些更新。幸运的是,它可以正常工作,并且希望它将保持这种状态。


34
我想对这个答案进行标记,因为它确实向您展示了如何创建具有唯一索引的新表,正如上面的jonstjohn的答案告诉您如何更新现有表。它们执行相同的操作,尽管仅取决于您是创建新表还是更新现有表。:)
GazB 2012年

3
所有反引号是什么,它们有一定用途吗?
2013年

8
它是从Adminer(www.adminer.org)输出的,该Adminer自动插入了这些反引号,因此用作列名的mysql关键字冲突不会有问题。
Frodik

50

如果您在行中具有NULL值,则多列唯一索引在MySQL中不起作用,因为MySQL将NULL视为唯一值,并且至少当前在多列索引中没有逻辑可以解决。是的,这种行为是疯狂的,因为它限制了许多多列索引的合法应用程序,但事实就是如此……到目前为止,这是一个在MySQL上标有“无法修复”的错误错误跟踪...


11
有两点需要澄清:1)这种行为并不成立ENGINE BDB,并且,2)这是有记录的行为,尽管恕我直言,鉴于它可能令人惊讶/令人不愉快,因此没有公开的记录。有关讨论,请参见MySQL错误25544 bugs.mysql.com/bug.php?id=25544
pilcrow,2010年

2
感谢NULL提示,解决了我遇到的问题...我想我将使用哈希校验和
Daniel Doezema

7
这不是答案。它应该是对原始问题的评论。
有限赎罪2015年

官方文档说:请注意,从MySQL 5.1开始,不再支持BDB。
George D.

2
很好的信息,但不是答案。仅与问题相关。
Billynoah

23

你试过这个吗?

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

什么埃里克说作品对我蛮好:UNIQUE KEY thekey`( ,,user )`。我使用的是MYSQL 5.5.24版,如果正在使用,甚至可以在PHPMYADMIN中进行设置。我正在使用PMA的3.5.1版本。emailaddress
WQC 2012年

在MySql 5.6中进行了尝试。从第一次尝试开始。谢谢埃里克!
劳伦斯

11

这适用于MySQL 5.5.32版

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

1
列名称上没有单引号似乎可以正常工作。
Pratik Singhal

7

MySql 5或更高版本的行为如下(我刚刚测试过):

  • 您可以定义涉及可空列的唯一约束。假设您定义一个唯一的约束(A,B),其中A不可为空,而B为
  • 在评估这样的约束时,您可以拥有(A,null)任意次(相同的A值!)
  • 您只能有一对(A,不能为空B)

范例:PRODUCT_NAME,PRODUCT_VERSION'glass',null'glass',null'wine',1

现在,如果您尝试再次插入(“葡萄酒” 1),它将报告违反约束的情况。


感谢您的解释。我有唯一的(A,B,C),但我不知道为什么它允许将null与相同的非null选项组合使用
AlexandruTopală19-10-18

6

您可以通过phpMyAdmin添加多列唯一索引。(我在4.0.4版中进行了测试)

导航到目标表的结构页面。将唯一索引添加到列之一。展开结构页面底部的“ 索引”列表,以查看刚刚添加的唯一索引。单击编辑图标,然后在下面的对话框中可以向该唯一索引添加其他列。


3

我这样做是这样的:

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

我对独特的约定index_nameTableName_Column1_Column2_Column3_uindex


2

要添加唯一索引,需要执行以下操作:

1)table_name
2)index_name
3)您要在其上添加索引的列

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

在您的情况下,我们可以如下创建唯一索引:

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

1

如果您想避免将来重复。创建另一个列,例如id2。

UPDATE tablename SET id2 = id;

现在在两列上添加唯一性:

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

1

如果要在mysql中创建表,请使用以下命令:

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

首先摆脱现有的重复

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;

然后添加唯一约束

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

用以下方法验证约束

SHOW CREATE TABLE votes;

请注意,如果用户,电子邮件,地址中的任何一个具有空值,则将被视为唯一。


0

对于PostgreSQL ...它对索引不起作用。它给了我一个错误,所以我这样做了:

alter table table_name
add unique(column_name_1,column_name_2);

PostgreSQL给唯一索引起了自己的名字。我想如果需要更改索引,可以在表的选项中更改索引的名称...

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.