MySQL ignore-t-il les valeurs nulles sur des contraintes uniques?

Réponses:

423

Oui, MySQL autorise plusieurs NULL dans une colonne avec une contrainte unique.

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;

Résultat:

x
NULL
NULL
1

Ce n'est pas vrai pour toutes les bases de données. SQL Server 2005 et les versions antérieures, par exemple, n'autorisent qu'une seule valeur NULL dans une colonne qui a une contrainte unique.

Mark Byers
la source
37
excellent commentaire sur la façon dont c'est vrai dans mysql, mais pas nécessairement en général.
user2910265
11
Selon la FAQ SQLite , le comportement est le même dans MySQL, PostgreSQL, SQLite, Oracle et Firebird.
Amir Ali Akbari
4
Veuillez mettre à jour votre réponse. SQLServer 2008+ le permet absolument, il vous suffit d'ajouter une clause WHERE ... en 2017, personne ne devrait de toute façon être sur une version plus ancienne que 2008 ... stackoverflow.com/questions/767657/…
Mathieu Turcotte
cette petite fonctionnalité a été très difficile de trouver une réponse qui ne nécessite pas d'ajouter une nouvelle colonne à la base de données ou de mettre à niveau MySQL sur une très ancienne application. Je cherchais vraiment une solution comme Postgres où je peux utiliser COALESCE mais il semble que la réponse soit toujours ce n'est pas un bug comment il est conçu. Il ne WHERE column IS NOT NULLsemble même pas me manquer car il n'est pas pris en charge dans ma version de MySQL. Quelqu'un sait où je pourrais regarder?
newdark-it
1
Remarque: cela fonctionne également avec des index uniques qui ont plus de colonnes. Donc, si vous voulez que les colonnes a, b et c soient uniques, vous pouvez toujours avoir dans le tableau des lignes doubles avec null, b, c
Mihai Crăiță
111

De la documentation :

"un index UNIQUE autorise plusieurs valeurs NULL pour les colonnes pouvant contenir NULL"

Cela s'applique à tous les moteurs sauf BDB .

Matthew Flaschen
la source
3
BDB n'est plus disponible sur les versions actuelles de mysql (à partir de 5.1.12).
Alim Özdemir
1
Mes tests semblent montrer que la base de données Java Derby v10.13.1.1. de même, n'autorise qu'un seul null dans une colonne avec un index unique.
chrisinmtown
7

Je ne sais pas si l'auteur demandait à l'origine si cela autorisait ou non les valeurs en double ou s'il y avait une question implicite ici demandant: "Comment autoriser les NULLvaleurs en double lors de l'utilisation UNIQUE?" Ou "Comment n'autoriser qu'une seule UNIQUE NULLvaleur?"

La question a déjà été répondue, oui, vous pouvez avoir des NULLvaleurs en double lors de l'utilisation de l' UNIQUEindex.

Depuis que je suis tombé sur cette réponse en cherchant "comment autoriser une UNIQUE NULLvaleur". Pour tous ceux qui pourraient tomber sur cette question en faisant de même, le reste de ma réponse est pour vous ...

Dans MySQL, vous ne pouvez pas avoir une UNIQUE NULLvaleur, mais vous pouvez avoir une UNIQUEvaleur vide en l'insérant avec la valeur d'une chaîne vide.

Avertissement: les valeurs numériques et autres que la chaîne peuvent être par défaut égales à 0 ou à une autre valeur par défaut.

bluegman991
la source
1
La contrainte n'a rien à voir avec l'index. En fait, vous ne pourrez même pas avoir une seule ligne avec une valeur NULL malgré le fait qu'il n'existe pas d'autre ligne de ce type.
Pijusn
1
@Pijusn Qu'entendez-vous par "la contrainte n'a rien à voir avec l'index?" Aussi à propos de votre deuxième phrase, je n'ai jamais dit que vous pourriez avoir une ligne avec une valeur NULL, c'est pourquoi j'ai déclaré au début de la publication, que c'est une solution uniquement s'il n'est pas déterminé à utiliser des valeurs nulles.
bluegman991
Ce que je voulais dire, c'est que l'ajout d'un nouvel élément échoue non pas à cause de la UNIQUEcontrainte mais à cause de la NOT NULLcontrainte. Je pense que cette réponse est sans rapport avec la question parce que la question concerne spécifiquement le comportement de la UNIQUEcontrainte.
Pijusn
@Pijusn Je t'ai eu. Vous avez raison, j'ai supprimé le libellé suggérant le contraire. J'ai mal lu la question. Mais je pense que la réponse peut toujours être utile pour les utilisateurs qui tombent sur cette question comme je l'ai fait en essayant de trouver un moyen d'avoir une valeur "rien" unique, mais qui autorisent par erreur la null-capacité.
bluegman991 du
1
J'ai trouvé cette réponse utile. Cependant, il est également répondu ici . Ce message était le premier résultat de ma recherche Google, bien que cette réponse et la question liée soient ce que je cherchais.
kingledion
5

Évitez les contraintes uniques nullables. Vous pouvez toujours placer la colonne dans une nouvelle table, la rendre non nulle et unique, puis remplir cette table uniquement lorsque vous avez une valeur pour celle-ci. Cela garantit que toute dépendance de clé sur la colonne peut être correctement appliquée et évite tout problème pouvant être causé par des valeurs NULL.

nvogel
la source
6
Oui, mais ce que vous proposez est presque exactement ce que mysql fait déjà dans les coulisses. Pourquoi réinventer la roue si cette fonctionnalité est intégrée?
ProfileTwist
2
Parce que ce n'est pas du SQL valide. Je pense que cette astuce sera utile pour tous ceux qui veulent (ou ont besoin) d'une conception indépendante de la base de données.
Arsen7
@ Arsen7 Et si vous avez plusieurs entreprises - chacune avec plusieurs clients. Vous stockez toutes les entreprises avec les adresses e-mail de leurs clients dans un seul fichier. Vous ne pouvez donc pas rendre email_address unique car différentes entreprises peuvent avoir le même client. Vous devez donc créer un index composite unique de business_id et email_address. Est-il possible de mettre cela dans un nouveau tableau - comme expliqué?
Gerhard Liebenberg
4
J'ai un cas où une colonne "e-mail" doit être unique OU nulle. Je devrais créer un nouveau tableau avec une seule colonne "e-mail" si je devais suivre vos conseils. S'appuyer sur ce comportement spécifique de Mysql est beaucoup plus facile et le résultat est le même. Le client ne se soucie pas de savoir si je stocke l'e-mail dans une nouvelle table ou non. De plus, la conception indépendante de la base de données est souvent trop surfaite. Pour de nombreux projets, vous ne pouvez pas et ne voudriez probablement pas simplement passer d'une base de données à une autre aussi facilement.
conradkleinespel
1
@djmj bien sûr, mais les dépendances fonctionnelles sont importantes pour la plupart des gens et la version de contrainte unique nullable n'impose pas les mêmes dépendances que la version BCNF. Ainsi, quelle option est plus ou moins pratique peut dépendre des dépendances importantes pour vous. C'est pourquoi il vaut la peine d'envisager de créer une nouvelle table.
nvogel