Maison > base de données > tutoriel mysql > Compréhension approfondie de Null dans SQL

Compréhension approfondie de Null dans SQL

巴扎黑
Libérer: 2017-05-01 13:43:00
original
1348 Les gens l'ont consulté

NULL représente l'inconnu et l'incertitude dans le monde de l'informatique et de la programmation. Bien que la traduction chinoise soit « vide », ce vide (nul) n’est pas si vide (vide). Null représente un état inconnu, un état futur. Par exemple, je ne sais pas combien d'argent Xiao Ming a en poche, mais je ne peux pas être sûr que ce soit 0. À l'heure actuelle, Null est utilisé dans les ordinateurs pour représenter. inconnu et incertain.

Même si les personnes maîtrisant SQL n'auront aucun doute sur Null, il est toujours difficile de trouver un article qui le résume de manière exhaustive. J'ai vu une version anglaise et ça m'a fait du bien.

Tony Hoare a inventé la référence nulle en 1965 et la considérait comme son « erreur d'un milliard de dollars ». Même aujourd'hui, 50 ans plus tard, les valeurs nulles en SQL sont toujours responsables de nombreuses erreurs courantes.

Jetons un coup d’œil à certaines des situations les plus choquantes.

Null ne prend pas en charge le jugement de taille/égalité

Pour les deux requêtes suivantes, quel que soit le nombre d'enregistrements présents dans la table des utilisateurs, les enregistrements renvoyés comportent 0 ligne :

select * from users where deleted_at = null;

– result: 0 rows

select * from users where deleted_at != null;

– result: 0 rows
Copier après la connexion

Comment est-ce possible ? Tout cela parce que null représente un type "inconnu". Autrement dit, cela n’a aucun sens d’utiliser des opérateurs conditionnels normaux pour comparer null avec d’autres valeurs. Null n'est pas égal à Null (compréhension approximative : une valeur inconnue ne peut pas être égale à une valeur inconnue, et la relation entre les deux est également inconnue, sinon les mathématiques et la logique seront gâchées).

– Remarque : le SQL suivant convient à MySQL. S'il s'agit d'Oracle, vous devez ajouter … from dual;

select null > 0;

– result: null

select null < 0;

– result: null

select null = 0;

– result: null

select null = null;

– result: null

select null != null;

– result: null
Copier après la connexion

. La bonne façon de comparer une valeur à null est d'utiliser le mot-clé is et l'opérateur is not :

select * from users

where deleted_at is null;

– result: 所有被标记为删除的 users
Copier après la connexion
select * from users

where deleted_at is not null;

– result: 所有被标记为删除的 users
Copier après la connexion

Si vous souhaitez déterminer si les valeurs de deux colonnes sont différentes, vous pouvez utiliser est distinct de :

select * from users

where has_address is distinct from has_photo

– result: 地址(address)或照片(photo)两者只有其一的用户
Copier après la connexion

pas avec Null

La sous-requête (sous-sélection) est un moyen très pratique de filtrer les données. Par exemple, si vous souhaitez interroger des utilisateurs qui n'ont aucun package, vous pouvez écrire une requête comme celle-ci :

select * from users 

where id not in (select user_id from packages)
Copier après la connexion

Mais à ce moment-là, si le user_id d'une ligne de la table packages est nul, un problème survient : le résultat renvoyé est vide ! Pour comprendre pourquoi cette chose étrange se produit, nous devons comprendre ce que le compilateur SQL a fait. exemple :

select * from users 

where id not in (1, 2, null)
Copier après la connexion

Cette instruction SQL sera convertie en :

select * from users 

where id != 1 and id != 2 and id != null
Copier après la connexion

Nous savons que le résultat de id != null est une valeur inconnue, null Et le résultat de l'opération AND entre n'importe quelle valeur et null est nul, il n'est donc équivalent à aucune autre condition. La raison de ce résultat est que la logique. la valeur de null n'est pas vraie.

Si les conditions sont inversées, il n'y aura aucun problème avec les résultats de la requête. Maintenant, nous interrogeons les utilisateurs avec des packages.

select * from users 

where id in (select user_id from packages)
Copier après la connexion

​De même, nous pouvons utiliser un exemple simple :

select * from users

where id in (1, 2, null)
Copier après la connexion

Ce SQL est converti en :

select * from users 

where id = 1 or id = 2 or id = null
Copier après la connexion

Étant donné que la clause Where est une série de conditions ou, peu importe si l'une d'elles aboutit à la valeur null. Les valeurs non vraies n'affectent pas les résultats de calcul des autres parties de la clause et équivalent à être ignorées.

Null et tri

Lors du tri, la valeur nulle est considérée comme la plus grande. Cela vous causera beaucoup de maux de tête lors du tri par ordre décroissant (décroissant), car la valeur nulle vient en premier.

La requête suivante consiste à afficher les classements des utilisateurs en fonction des scores, mais elle classe les utilisateurs sans scores au sommet

select name, points

from users

order by 2 desc;

– points 为 null 的记录排在所有记录之前!
Copier après la connexion

 ! Il existe deux manières d’envisager la résolution de ce type de problème. Le plus simple est d'utiliser coalesce pour éliminer l'effet de null :

– 在输出时将 null 转换为 0 :

select name, coalesce(points, 0)

from users

order by 2 desc;

– 输出时保留 null, 但排序时转换为 0 :

select name, points

from users

order by coalesce(points, 0) desc;
Copier après la connexion

Il existe une autre méthode qui nécessite la prise en charge de la base de données, qui consiste à spécifier s'il faut mettre la valeur nulle en premier ou en dernier lors du tri :

select name, coalesce(points, 0)

from users

order by 2 desc nulls last;
Copier après la connexion

Bien entendu, null peut également être utilisé pour éviter que des erreurs ne se produisent, telles que la gestion des erreurs d'opérations mathématiques lorsque le diviseur est nul.

Divisé par 0

Diviser par zéro est une erreur très pénible. SQL qui fonctionnait correctement hier s'est soudainement détérioré lorsqu'il a été divisé par 0. Une solution courante consiste à utiliser d’abord une instruction case pour déterminer si le dénominateur est 0, puis à effectuer l’opération de division.

select case when num_users = 0 then 0 

else total_sales/num_users end;
Copier après la connexion

La manière de faire l'instruction ase est en fait moche et le dénominateur est réutilisé. Si c'est une situation simple, ça va. Mais si le dénominateur est une expression très complexe, alors une tragédie surviendra : c'est difficile à lire, difficile à maintenir et à modifier, et il y aura beaucoup de bugs si vous n'y faites pas attention.

À ce stade, nous pouvons examiner les avantages de null. Utilisez nullif pour que le dénominateur devienne nul lorsqu'il est égal à 0. De cette façon, une erreur ne sera plus signalée lorsque num_users = 0, le résultat renvoyé devient nul.

select total_sales/nullif(num_users, 0);

nullif 是将其他值转为 null, 而Oracle的 nvl 是将 null 转换为其他值。
Copier après la connexion
Si vous ne voulez pas de null, mais que vous souhaitez convertir en 0 ou en d'autres nombres, vous pouvez utiliser la fonction de fusion basée sur le SQL précédent :

select coalesce(total_sales/nullif(num_users, 0), 0);

null 再转换回0
Copier après la connexion

Conclusion

Tony Hoare regrette peut-être son erreur, mais au moins le problème de null peut être facilement résolu. Alors allez pratiquer votre nouveau coup ultime et restez à l'écart de la fosse invalide (annulante) creusée par null !

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal