O MySQL ignora valores nulos em restrições exclusivas?

Respostas:

422

Sim, o MySQL permite vários NULLs em uma coluna com uma restrição única.

CREATE TABLE table1 (x INT NULL UNIQUE);
INSERT table1 VALUES (1);
INSERT table1 VALUES (1);   -- Duplicate entry '1' for key 'x'
INSERT table1 VALUES (NULL);
INSERT table1 VALUES (NULL);
SELECT * FROM table1;

Resultado:

x
NULL
NULL
1

Isso não é verdade para todos os bancos de dados. O SQL Server 2005 e mais antigo, por exemplo, permite apenas um único valor NULL em uma coluna que possui uma restrição exclusiva.

Mark Byers
fonte
37
excelente comentário sobre como isso é verdade no mysql, mas não necessariamente em geral.
user2910265
11
De acordo com as perguntas frequentes do SQLite , o comportamento é o mesmo no MySQL, PostgreSQL, SQLite, Oracle e Firebird.
Amir Ali Akbari
4
Atualize sua resposta. O SQLServer 2008+ permite isso absolutamente, basta adicionar uma cláusula WHERE ... em 2017, ninguém deveria estar em uma versão anterior a 2008 de qualquer maneira ... stackoverflow.com/questions/767657/…
Mathieu Turcotte
Esse pequeno recurso tem sido muito difícil de encontrar uma resposta, que não requer a adição de uma nova coluna ao banco de dados ou a atualização do MySQL em um aplicativo muito antigo. Eu estava realmente procurando por uma solução como o Postgres, onde eu possa usar o COALESCE, mas parece que a resposta é sempre que não é um erro de como é projetada. Nem WHERE column IS NOT NULLparece falhar comigo, pois não é suportado na minha versão do MySQL. Alguém sabe onde eu poderia procurar?
Newdark-it
1
nota: isso também funciona também com índices únicos que têm mais colunas. Então se você quer colunas a, b e c ser único você ainda pode ter na tabela fileiras duplas com null, b, c
Mihai Crăiţă
111

Dos documentos :

"um índice UNIQUE permite vários valores NULL para colunas que podem conter NULL"

Isso se aplica a todos os mecanismos, exceto o BDB .

Matthew Flaschen
fonte
3
O BDB não está mais disponível nas versões atuais do mysql (começando com 5.1.12).
Alim Özdemir
1
Meu teste parece mostrar que o banco de dados Java Derby v10.13.1.1. Da mesma forma, permite apenas um nulo em uma coluna com um índice exclusivo.
chrisinmtown
7

Não tenho certeza se o autor originalmente estava apenas perguntando se isso permite ou não valores duplicados ou se havia uma pergunta implícita aqui perguntando: "Como permitir NULLvalores duplicados durante o uso UNIQUE?" Ou "Como permitir apenas umUNIQUE NULL valor?"

A pergunta já foi respondida; sim, você pode ter NULLvalores duplicados enquanto usa o UNIQUEíndice.

Desde que me deparei com essa resposta enquanto procurava por "como permitir um UNIQUE NULLvalor". Para quem mais se deparar com essa pergunta enquanto faz o mesmo, o restante da minha resposta é para você ...

No MySQL, você não pode ter um UNIQUE NULLvalor, no entanto, pode ter um UNIQUEvalor vazio, inserindo o valor de uma string vazia.

Aviso: Numérico e tipos diferentes de sequência podem ter como padrão 0 ou outro valor padrão.

bluegman991
fonte
1
A restrição não tem nada a ver com o índice. De fato, você nem conseguirá ter uma única linha com valor NULL, apesar de não haver outra linha.
Pijusn
1
@Pijusn O que você quer dizer com "restrição não tem nada a ver com índice?" Também sobre sua segunda frase, eu nunca disse que você poderia ter uma linha com um valor NULL, por isso afirmei no início do post, que essa é uma solução apenas se ele não usar valores nulos.
precisa saber é o seguinte
O que eu quis dizer é que a adição de novo elemento falha não por causa da UNIQUErestrição, mas por causa da NOT NULLrestrição. Eu acho que essa resposta é irrelevante para a pergunta, porque a pergunta é especificamente sobre o comportamento da UNIQUErestrição.
Pijusn 15/01/19
@Pijusn eu peguei você. Você está certo, removi o texto sugerindo o contrário. Eu li mal a pergunta. Mas acredito que a resposta ainda pode ser útil para os usuários que se deparam com essa pergunta, como eu, enquanto tentava encontrar uma maneira de ter um valor exclusivo de "nada", mas, por engano, permitem a capacidade nula.
precisa saber é o seguinte
1
Achei esta resposta útil. No entanto, também é respondido aqui . Este post foi o primeiro resultado da minha pesquisa no google, embora essa resposta e a pergunta vinculada fossem o que eu estava procurando.
kingledion
5

Evite restrições exclusivas anuláveis. Você sempre pode colocar a coluna em uma nova tabela, torná-la não nula e exclusiva e, em seguida, preencher essa tabela somente quando tiver um valor para ela. Isso garante que qualquer dependência de chave na coluna possa ser aplicada corretamente e evita problemas que possam ser causados ​​por nulos.

nvogel
fonte
6
Sim, mas o que você propõe é quase exatamente o que o mysql já faz nos bastidores. Por que reinventar a roda se essa funcionalidade está embutida?
precisa
2
Porque não é SQL válido. Acredito que essa dica será útil para todos que desejam (ou precisam) um design independente de banco de dados.
precisa saber é o seguinte
@ Arsen7 E se você tiver vários negócios - cada um com vários clientes. Você armazena todas as empresas com os endereços de e-mail de seus clientes em um arquivo. Portanto, você não pode tornar o email_address exclusivo porque empresas diferentes podem ter o mesmo cliente. Portanto, você precisa criar um índice exclusivo composto de business_id e email_address. É possível colocar isso em uma nova tabela - como explicado?
Gerhard Liebenberg 02/02
4
Eu tenho um caso em que uma coluna "email" precisa ser única OU nula. Eu precisaria criar uma nova tabela com uma única coluna "email" para seguir seus conselhos. Contar com esse comportamento específico do Mysql é muito mais fácil e o resultado é o mesmo. O cliente não se importa se eu armazeno o email em uma nova tabela ou não. Além disso, o design independente de banco de dados geralmente é superestimado. Para muitos projetos, você não pode e provavelmente não mudaria de um banco de dados para outro com tanta facilidade.
conradkleinespel
1
@djmj claro, mas as dependências funcionais são importantes para a maioria das pessoas e a versão de restrição exclusiva anulável não impõe as mesmas dependências que a versão do BCNF. Portanto, qual opção é mais ou menos prática pode depender de quais dependências são importantes para você. É por isso que vale a pena considerar criar uma nova tabela.
nvogel