Como especifico uma restrição exclusiva para várias colunas no MySQL?

865

Eu tenho uma mesa:

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

Agora, quero tornar as colunas usuário, email e endereço exclusivos (juntos).

Como faço isso no MySql?

Claro que o exemplo é apenas ... um exemplo. Então, por favor, não se preocupe com a semântica.

Niyaz
fonte

Respostas:

1436
ALTER TABLE `votes` ADD UNIQUE `unique_index`(`user`, `email`, `address`);
Jonstjohn
fonte
31
Isso funcionaria corretamente com a cláusula ON DUPLICATE KEY das instruções INSERT? Ou seja, se eu estivesse tentando inserir uma linha que conflitasse com os valores de usuário / email / endereço de outra linha, o INSERT executaria as ações especificadas pela cláusula ON DUPLICATE KEY?
Clizzin
6
Dessa forma, a combinação de três seria única? Ou todas as três colunas individuais seriam únicas?
Gary Lindahl
95
Para as pessoas que usam o MySQL workbench: vá para a aba Indexes e selecione UNIQUE como seu tipo. Dê seu índice de um nome e verificar as colunas apropriadas na secção "Índice Colunas"
Pakman
10
Como eu, se alguém encontrou isso nos mecanismos de pesquisa ... e para responder à pergunta de Clizzin sobre se o ON DUPLICATE KEY funcionará com uma chave composta - absolutamente funcionará, no entanto, será necessário alguns pequenos ajustes na sintaxe. consulte stackoverflow.com/questions/9537710/…
Joe
2
como fazê-lo funcionar mesmo com valor NULL. Se inserirmos duas mesmas linhas com valor NULL, isso não está funcionando ...
Wasim A.
237

Eu tenho uma tabela 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 a UNIQUE KEY funciona da maneira esperada, permitindo várias linhas NULL de id_box_elements e id_router.

Estou executando o MySQL 5.1.42, então provavelmente houve alguma atualização sobre o problema discutido acima. Felizmente, funciona e espero que continue assim.

Frodik
fonte
34
Eu queria marcar essa resposta, pois mostra como criar uma nova tabela com um índice exclusivo, onde a resposta de jonstjohn acima informa como atualizar uma tabela existente. Eles fazem o mesmo, embora apenas dependa se você está criando uma nova tabela ou atualizando uma tabela existente. :)
GazB
3
O que há com todas as citações anteriores, elas servem a algum propósito?
puk 16/05
8
Sua saída é do Adminer (www.adminer.org), que insere essas aspas automaticamente, para que não haja problemas com a colisão de palavras-chave mysql usadas como nomes de colunas.
Frodik
50

Os índices exclusivos de várias colunas não funcionam no MySQL se você tiver um valor NULL em linha, pois o MySQL trata NULL como um valor exclusivo e, pelo menos atualmente, não tem lógica para contorná-lo em índices de várias colunas. Sim, o comportamento é insano, porque limita muitas aplicações legítimas de índices de várias colunas, mas é o que é ... Até agora, é um bug que foi carimbado com "não será corrigido" no MySQL rastrear insetos ...

niksoft
fonte
11
Dois pontos de esclarecimento: 1) esse comportamento não se aplica ENGINE BDBe, 2) esse é um comportamento documentado , embora IMHO não tenha sido suficientemente documentado, dado o quão surpreendente / desagradável pode ser. Veja o bug 25544 do MySQL bugs.mysql.com/bug.php?id=25544 para uma discussão.
pilcrow
2
Obrigado pelo
aviso NULL
7
Esta não é uma resposta. Deve ser um comentário para a pergunta original.
Expiação limitada
Os documentos oficiais dizem: Observe que, a partir do MySQL 5.1, o BDB não é mais suportado.
George D.
2
Informações muito boas, mas não uma resposta. É apenas periférico relacionado à questão.
precisa saber é
23

Você já tentou isso?

UNIQUE KEY `thekey` (`user`,`email`,`address`)
Erick
fonte
O Erick disse funciona muito bem para mim: UNIQUE KEY thekey` ( user, email, address) `. Estou usando o MYSQL versão 5.5.24. Você pode definir isso mesmo no PHPMYADMIN se estiver usando. Estou usando a versão 3.5.1 do PMA.
WQC
Tentei com o MySql 5.6. Funciona desde a primeira tentativa. Obrigado Erick!
21432 Lawrence
11

Isso funciona para o mysql versão 5.5.32

ALTER TABLE  `tablename` ADD UNIQUE (`column1` ,`column2`);
rizon
fonte
1
Parece funcionar sem as aspas simples no nome da coluna.
Pratik Singhal
7

O MySql 5 ou superior se comporta assim (eu acabei de testar):

  • você pode definir restrições exclusivas envolvendo colunas anuláveis. Digamos que você defina uma restrição exclusiva (A, B) em que A não é anulável, mas B é
  • ao avaliar essa restrição, você pode ter (A, nulo) quantas vezes quiser (o mesmo valor A!)
  • você pode ter apenas um par (A, não nulo B)

Exemplo: PRODUCT_NAME, PRODUCT_VERSION 'copo', nulo 'copo', nulo 'vinho', 1

Agora, se você tentar inserir ('wine' 1) novamente, ele relatará uma violação de restrição Espero que isso ajude

Cristian Botiza
fonte
obrigado por explicar. Tenho única (A, B, C) e eu não sabia por que permitiu que combinações de NULL com opções mesmos não nulos
Alexandru Topala
6

Você pode adicionar índices exclusivos de várias colunas via phpMyAdmin . (Eu testei na versão 4.0.4)

Navegue para a página de estrutura da sua tabela de destino. Adicione um índice exclusivo a uma das colunas. Expanda a lista Índices na parte inferior da página da estrutura para ver o índice exclusivo que você acabou de adicionar. Clique no ícone de edição e, na caixa de diálogo a seguir, você pode adicionar colunas adicionais a esse índice exclusivo.

Vince K
fonte
3

Eu faço assim:

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

Minha convenção para um único index_nameé TableName_Column1_Column2_Column3_uindex.

Sam Malayek
fonte
2

Para adicionar um índice exclusivo, é necessário o seguinte:

1) table_name
2) index_name
3) colunas nas quais você deseja adicionar índice

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

No seu caso, podemos criar um índice exclusivo da seguinte maneira:

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

Se você deseja evitar duplicatas no futuro. Crie outra coluna, diga id2.

UPDATE tablename SET id2 = id;

Agora adicione o exclusivo em duas colunas:

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

Se você estiver criando tabela no mysql, use o seguinte:

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
fonte
0

Primeiro, livre-se das duplicatas 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;

Em seguida, adicione a restrição exclusiva

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

Verifique a restrição com

SHOW CREATE TABLE votes;

Observe que o usuário, email, endereço será considerado único se algum deles tiver valor nulo.

Ganesh Krishnan
fonte
0

Para PostgreSQL ... Não funcionou para mim com índice; isso me deu um erro, então eu fiz isso:

alter table table_name
add unique(column_name_1,column_name_2);

O PostgreSQL deu ao índice exclusivo seu próprio nome. Eu acho que você pode alterar o nome do índice nas opções da tabela, se for necessário alterar ...

bugthefifth
fonte