Dans le serveur SQL, si vous avez nullParam=NULL
une clause where, la valeur est toujours false. Ceci est contre-intuitif et m'a causé de nombreuses erreurs. Je comprends que les mots clés IS NULL
et IS NOT NULL
sont la bonne façon de procéder. Mais pourquoi le serveur SQL se comporte-t-il de cette façon?
sql
sql-server
null
Byron Whitlock
la source
la source
Réponses:
Considérez le nul comme "inconnu" dans ce cas (ou "n'existe pas"). Dans l'un ou l'autre de ces cas, vous ne pouvez pas dire qu'ils sont égaux, car vous ne connaissez pas la valeur de l'un ou l'autre. Ainsi, null = null est évalué comme non vrai (faux ou nul, selon votre système), car vous ne connaissez pas les valeurs pour dire qu'elles SONT égales. Ce comportement est défini dans la norme ANSI SQL-92.
EDIT: Cela dépend de votre paramètre ansi_nulls . si vous avez ANSI_NULLS désactivé, cela évaluera à vrai. Exécutez le code suivant pour un exemple ...
la source
(NaN == NaN) == false && (NaN != Nan) == false && (NaN < NaN) == false && ...
- parce que, eh bien, si ce n'est pas un nombre, vous ne pouvez tout simplement pas en dire beaucoup; c'est quelque chose d'inconnu. Le concept est solide, même s'il n'est pas intuitif pour les personnes qui ne l'ont jamais vu auparavant.NULL
expression SQL peut être traitée comme une variable mathématique distincte . Une expressionNULL = NULL
doit donc être traitée commex = y
, oùx
ety
sont des variables indépendantes. Maintenant, si quelqu'un vous demande, quelle est la valeur dex = y
? La seule réponse raisonnable est «certainsz
». Nous avons donc(x = y) = z
- ou, transcrivant retour à SQL,(NULL = NULL) = NULL
.Quel âge a Frank? Je ne sais pas (nul).
Quel âge a Shirley? Je ne sais pas (nul).
Frank et Shirley ont-ils le même âge?
La bonne réponse devrait être "Je ne sais pas" (nul), pas "non", car Frank et Shirley ont peut- être le même âge, nous ne le savons tout simplement pas.
la source
null = null
cèdeFALSE
, nonNULL
.J'espère ici clarifier ma position.
Cette
NULL = NULL
évaluationFALSE
est fausse. Hacker et Mister ont répondu correctementNULL
. Voici pourquoi. Dewayne Christensen m'a écrit, dans un commentaire à Scott Ivey :Ils peuvent être différents ou être égaux, vous ne le savez pas tant que l'on n'a pas ouvert les deux cadeaux. Qui sait? Vous avez invité deux personnes qui ne se connaissent pas et qui vous ont fait le même cadeau - rare, mais pas impossible § .
Alors la question: ces deux cadeaux INCONNU sont-ils identiques (égaux, =)? La bonne réponse est: INCONNU (c'est-à-dire
NULL
).Cet exemple visait à démontrer que ".. (
false
ounull
, selon votre système) .." est une réponse correcte - ce n'est pas, seulementNULL
est correcte en 3VL (ou est-ce que vous acceptez un système qui donne de mauvaises réponses? )Une réponse correcte à cette question doit souligner ces deux points:
Je répète donc: SQL ne sert à rien de forcer à interpréter la propriété réflexive de l'égalité, qui stipule que:
.. dans un 3VL (
TRUE
,FALSE
,NULL
). L'attente des personnes se conformerait à 2VL (TRUE
,FALSE
qui même dans SQL est valable pour toutes les autres valeurs), à savoirx = x
évaluer toujoursTRUE
, pour toute valeur possible de x - sans exception.Notez également que les NULL sont des " non-valeurs valides" " (comme leurs apologistes le prétendent) que l'on peut attribuer comme valeurs d'attribut (??) dans le cadre des variables de relation. Ce sont donc des valeurs acceptables de chaque type (domaine), pas seulement du type d'expressions logiques.
Et c'était mon point :,
NULL
comme valeur, est une "bête étrange". Sans euphémisme, je préfère dire: non - sens .Je pense que cette formulation est beaucoup plus claire et moins discutable - désolé pour ma faible maîtrise de l'anglais.
C'est seulement l' un des problèmes de NULLs. Mieux vaut les éviter complètement, si possible.
§ nous sommes préoccupés par les valeurs ici, donc le fait que les deux présents soient toujours deux objets physiques différents ne constitue pas une objection valable; si vous n'êtes pas convaincu je suis désolé, ce n'est pas ici le lieu pour expliquer la différence entre la sémantique valeur et "objet" (l'algèbre relationnelle a une sémantique de valeur dès le début - voir le principe d'information de Codd; je pense que certains implémenteurs de SGBD SQL ne ne se soucie même pas d'une sémantique commune).
§§ à ma connaissance, c'est un axiome accepté (sous une forme ou une autre, mais toujours interprété dans un 2VL) depuis l'antiquité et cela précisément parce qu'il est si intuitif. 3VLs (est une famille de logiques en réalité) est un développement beaucoup plus récent (mais je ne sais pas quand a été développé pour la première fois).
Note latérale: si quelqu'un introduit des types de bas , d' unité et d' option comme tentatives de justifier les NULL SQL, je ne serai convaincu qu'après un examen assez détaillé qui montrera comment les implémentations SQL avec des NULL ont un système de type sonore et clarifiera, enfin, ce que sont vraiment les NULL (ces «valeurs pas tout à fait»).
Dans ce qui suit, je citerai quelques auteurs. Toute erreur ou omission est probablement la mienne et non celle des auteurs originaux.
Joe Celko sur les NULL SQL
Je vois Joe Celko souvent cité sur ce forum. Apparemment, c'est un auteur très respecté ici. Alors, je me suis dit: "qu'est-ce qu'il a écrit sur les NULL SQL? Comment explique-t-il les nombreux problèmes des NULL?". Un de mes amis a une version ebook du SQL de Joe Celko pour les smarties: programmation SQL avancée, 3e édition . Voyons voir.
Tout d'abord, la table des matières. Ce qui me frappe le plus, c'est le nombre de fois où NULL est mentionné et dans les contextes les plus variés:
etc. Cela me semble un "cas spécial méchant".
J'entrerai dans certains de ces cas avec des extraits de ce livre, en essayant de me limiter à l'essentiel, pour des raisons de copyright. Je pense que ces citations relèvent de la doctrine du «fair use» et qu'elles peuvent même inciter à acheter le livre - j'espère donc que personne ne se plaindra (sinon je devrai en supprimer la plupart, sinon la totalité). De plus, je m'abstiendrai de signaler des extraits de code pour la même raison. Désolé pour ça. Achetez le livre pour en savoir plus sur le raisonnement datailed.
Numéros de page entre parenthèses dans ce qui suit.
Encore une fois, cette "valeur mais pas tout à fait une valeur" absurde. Le reste me paraît tout à fait raisonnable.
À propos de SQL, NULL et infini:
Les implémentations SQL sont indécises sur ce que signifie vraiment NULL dans des contextes particuliers:
Joe Celko citant David McGoveran et CJ Date:
NULL en tant que toxicomanie :
Mon unique objection ici est de «les utiliser correctement», ce qui interagit mal avec des comportements d'implémentation spécifiques.
(séparateur)
Mais INCONNU est une source de problèmes en soi, de sorte que CJ Date, dans son livre cité ci-dessous, recommande au chapitre 4.5. Éviter les valeurs nulles dans SQL :
Lisez "ASIDE" sur INCONNU, également lié ci-dessous.
(séparateur)
Objection: NULL confond même les personnes qui connaissent bien SQL, voir ci-dessous.
(séparateur)
(séparateur)
(séparateur)
(séparateur)
(séparateur)
(séparateur)
Discussion GROUPE BY:
Cela signifie que pour GROUP BY, la clause NULL = NULL ne s'évalue pas à NULL, comme dans 3VL, mais à TRUE.
Le standard SQL est déroutant:
Etc. Je pense que c'est assez par Celko.
Date CJ sur les NULL SQL
CJ Date est plus radical sur les NULL: évitez les NULL en SQL, point final. En fait, le chapitre 4 de sa théorie SQL et relationnelle: Comment écrire du code SQL précis est intitulé "PAS DE DUPLICATES, PAS DE NULLS", avec des sous-chapitres "4.4 Qu'est-ce qui ne va pas avec les Nulls?" et "4.5 Eviter les Nulls en SQL" (suivez le lien: grâce à Google Livres, vous pouvez lire certaines pages en ligne).
Fabian Pascal sur les NULL SQL
De ses problèmes pratiques dans la gestion de base de données - Une référence pour le praticien de la pensée (pas d'extraits en ligne, désolé):
la source
NULL
n'est pas une valeur.(NULL = NULL) -> FALSE
. Pour citer la documentation pourANSI_NULLS
: "Lorsque ON est spécifié, toutes les comparaisons à une valeur nulle sont évaluées à INCONNU . Lorsque OFF est spécifié, les comparaisons de valeurs non UNICODE à une valeur nulle sont évaluées à TRUE si les deux valeurs sont NULL."Cela dépend peut-être, mais je pensais que les
NULL=NULL
évaluationsNULL
ressemblaient à la plupart des opérations avec NULL comme opérande.la source
Ce n'est pas parce que vous ne savez pas ce que sont deux choses. Si quand vous pensez à
NULL
"NULL" (chaîne), vous voulez probablement un test d'égalité différent comme leIS DISTINCT FROM
AND de PostgresqlIS NOT DISTINCT FROM
Extrait de la documentation PostgreSQL sur «Fonctions et opérateurs de comparaison»
la source
Le concept de NULL est pour le moins discutable. Codd a introduit le modèle relationnel et le concept de NULL en contexte (et a continué en proposant plus d'un type de NULL!) Cependant, la théorie relationnelle a évolué depuis les écrits originaux de Codd: certaines de ses propositions ont depuis été abandonnées (par exemple, la clé primaire) et d'autres n'ont jamais été pris en compte (par exemple les opérateurs theta). Dans la théorie relationnelle moderne (véritable théorie relationnelle, je dois souligner) NULL n'existe tout simplement pas. Voir le troisième manifeste.http://www.thethirdmanifesto.com/
Le langage SQL souffre du problème de la rétrocompatibilité. NULL a trouvé son chemin dans SQL et nous sommes coincés avec lui. On peut soutenir que l'implémentation de
NULL
SQL est imparfaite (l'implémentation de SQL Server rend les choses encore plus compliquées en raison de sonANSI_NULLS
option).Je recommande d'éviter l'utilisation de colonnes NULLable dans les tables de base.
Même si je ne devrais peut-être pas être tenté, je voulais juste apporter ma propre correction sur la façon dont
NULL
fonctionnement de SQL:NULL
=NULL
évalue àUNKNOWN
.UNKNOWN
est une valeur logique.NULL
est une valeur de données.C'est facile à prouver, par exemple
SELECT NULL = NULL
génère correctement une erreur dans SQL Server. Si le résultat était une valeur de données, nous nous attendrions à voir
NULL
, comme certaines réponses ici (à tort) suggèrent que nous le ferions.La valeur logique
UNKNOWN
est traitée différemment dans SQL DML et SQL DDL respectivement.Dans SQL DML,
UNKNOWN
lignes sont supprimées du jeu de résultats.Par exemple:
Le
INSERT
réussit pour cette ligne, même si laCHECK
condition est résolueNULL = NULL
. Ceci doit être défini dans la norme SQL-92 ("ANSI"):Lisez à nouveau attentivement, en suivant la logique.
En anglais simple, notre nouvelle ligne ci-dessus reçoit le «bénéfice du doute» sur le fait d'être
UNKNOWN
et d' être autorisé à passer.Dans SQL DML, la règle de la
WHERE
clause est beaucoup plus simple à suivre:En anglais simple, les lignes évaluées
UNKNOWN
sont supprimées du jeu de résultats.la source
Chez technet, il y a une bonne explication du fonctionnement des valeurs nulles.
Null signifie inconnu.
Par conséquent, l'expression booléenne
valeur = null
n'évalue pas à false, il évalue à null, mais si c'est le résultat final d'une clause where, alors rien n'est retourné. C'est une manière pratique de le faire, car renvoyer null serait difficile à concevoir.
C'est intéressant et très important de comprendre ce qui suit:
Si dans une requête nous avons
et
puis
"value = @ param" évalue à null
"@param est nul" évalue à vrai
"id = @ anotherParam" évalue à vrai
Ainsi l'expression à évaluer devient
(nul ou vrai) et vrai
Nous pourrions être tentés de penser qu'ici "nul ou vrai" sera évalué à nul et donc l'expression entière devient nulle et la ligne ne sera pas retournée.
Ce n'est pas le cas. Pourquoi?
Parce que "nul ou vrai" est évalué à vrai, ce qui est très logique, puisque si un opérande est vrai avec l'opérateur Or, quelle que soit la valeur de l'autre opérande, l'opération retournera vrai. Ainsi, peu importe que l'autre opérande soit inconnu (nul).
Nous avons donc finalement true = true et donc la ligne sera retournée.
Remarque: avec la même logique limpide que «nul ou vrai» évalue à vrai, «nul et vrai» s'évalue à nul.
Mise à jour:
Ok, juste pour le rendre complet, je veux ajouter le reste ici aussi, ce qui s'avère assez amusant par rapport à ce qui précède.
"null ou faux" est évalué à null, "null et faux" est évalué à faux. :)
La logique est bien sûr toujours aussi évidente qu'avant.
la source
Parce que
NULL
signifie «valeur inconnue» et deux valeurs inconnues ne peuvent pas être égales.Donc, si dans notre logique
NULL
N ° 1 est égal àNULL
N ° 2, alors nous devons dire que d'une manière ou d'une autre:où la valeur connue
-1
N ° 1 est égale à-1
N ° 2la source
nullParam1 = -1
etnullParam2 =NULL
et accident d'avion ... devrait êtreISNULL(NULLIF(@nullParam1, @nullParam2), NULLIF(@nullParam2, nullParam1)) IS NULL
Les réponses ici semblent toutes venir d'un point de vue CS, je veux donc en ajouter une du point de vue du développeur.
Pour un développeur NULL est très utile. Les réponses ici disent que NULL signifie inconnu, et peut-être que dans la théorie CS, c'est vrai, je ne m'en souviens pas, cela fait un moment. Dans le développement réel, du moins d'après mon expérience, cela se produit environ 1% du temps. L'autre 99% est utilisé pour les cas où la valeur n'est pas INCONNUE mais elle est CONNUE ABSENTE.
Par exemple:
Client.LastPurchase
, pour un nouveau client. Ce n'est pas inconnu, on sait qu'il n'a pas encore fait d'achat.Lors de l'utilisation d'un ORM avec un mappage Table par hiérarchie de classes , certaines valeurs ne sont tout simplement pas mappées pour certaines classes.
Lors du mappage d'une arborescence, une racine aura généralement
Parent = NULL
Et beaucoup plus...
Je suis sûr qu'à un moment donné
WHERE value = NULL
, la plupart des développeurs ont écrit , n'ont obtenu aucun résultat, et c'est ainsi qu'ils ont appris laIS NULL
syntaxe. Regardez simplement combien de votes cette question et les votes liés ont.Les bases de données SQL sont un outil et elles doivent être conçues de la manière la plus facile à comprendre pour leurs utilisateurs.
la source
NULL n'est égal à rien, pas même à lui-même. Ma solution personnelle pour comprendre le comportement de NULL est d'éviter de l'utiliser autant que possible :).
la source
La question:
une inconnue équivaut-elle à une autre inconnue?
(NULL = NULL)
Cette question est une question à laquelle personne ne peut répondre, elle est donc par défaut true ou false en fonction de votre paramètre ansi_nulls.
Cependant la question:
cette variable inconnue est-elle inconnue?
Cette question est très différente et peut être répondue avec vrai.
nullVariable = null compare les valeurs
nullVariable est null compare l'état de la variable
la source
La confusion provient du niveau d'indirection (abstraction) qui résulte de l'utilisation de NULL .
Revenant à l'analogie de «ce qu'il y a sous le sapin de Noël», «Inconnu» décrit l'état des connaissances sur ce qui se trouve dans l'encadré A.
Donc, si vous ne savez pas ce qu'il y a dans la case A, vous dites que c'est "Inconnu", mais cela ne veut pas dire que "Inconnu" est à l'intérieur de la case . Quelque chose d'autre qu'inconnu se trouve dans la boîte, peut-être une sorte d'objet, ou peut-être rien n'est dans la boîte.
De même, si vous ne savez pas ce qu'il y a dans la case B, vous pouvez étiqueter votre état de connaissance du contenu comme étant "inconnu".
Alors, voici le kicker: votre état de connaissance sur la boîte A est égal à votre état de connaissance sur la boîte B . (Votre état de connaissance dans les deux cas est «Inconnu» ou «Je ne sais pas ce qu'il y a dans la boîte».) Mais le contenu des boîtes peut être égal ou non.
Pour revenir à SQL, idéalement, vous ne devriez pouvoir comparer les valeurs que lorsque vous savez ce qu'elles sont. Malheureusement, l'étiquette qui décrit un manque de connaissances est stockée dans la cellule elle - même , nous sommes donc tentés de l'utiliser comme valeur. Mais nous ne devrions pas utiliser cela comme une valeur, car cela conduirait à "le contenu de la boîte A égale le contenu de la boîte B lorsque nous ne savons pas ce qui est dans la boîte A et / ou que nous ne savons pas ce qui est dans la boîte B. (Logiquement, l'implication "si je ne sais pas ce qu'il y a dans la case A et si je ne sais pas ce qui se trouve dans la case B, alors ce qui se trouve dans la case A = ce qui se trouve dans la case B" est fausse.)
Ouais, cheval mort.
la source
MSDN a un bel article descriptif sur les valeurs nulles et la logique à trois états qu'elles engendrent.
En bref, la spécification SQL92 définit NULL comme inconnu et NULL utilisé dans les opérateurs suivants provoque des résultats inattendus pour les non-initiés:
la source
null est inconnu dans SQL donc nous ne pouvons pas nous attendre à ce que deux inconnues soient identiques.
Cependant, vous pouvez obtenir ce comportement en définissant ANSI_NULLS sur Off (il est activé par défaut) Vous pourrez utiliser l'opérateur = pour les valeurs nulles
la source
null
, apprenez à la comprendre ou modifiez simplement la table pour avoir des types int et mettre à jour les colonnes.Vous travaillez pour le gouvernement en enregistrant des informations sur les citoyens. Cela comprend la carte d'identité nationale de chaque personne dans le pays. Un enfant a été laissé à la porte d'une église il y a 40 ans, personne ne sait qui sont ses parents. L'ID du père de cette personne est
NULL
. Deux de ces personnes existent. Comptez les personnes qui partagent le même identifiant de père avec au moins une autre personne (personnes qui sont frères et sœurs). Comptez-vous ces deux-là aussi?La réponse est non, non, car nous ne savons pas si ce sont des frères et sœurs ou non.
Supposons que vous n'ayez pas d'
NULL
option, et que vous utilisiez à la place une valeur prédéterminée pour représenter «l'inconnu», peut-être une chaîne vide ou le chiffre 0 ou un caractère *, etc. Ensuite, vous auriez dans vos requêtes que * = * , 0 = 0, et «» = «», etc. Ce n'est pas ce que vous voulez (comme dans l'exemple ci-dessus), et comme vous pourriez souvent oublier ces cas (l'exemple ci-dessus est un cas marginal clair en dehors de la pensée quotidienne ordinaire ), alors vous avez besoin de la langue dont vous vous souviendrez que ceNULL = NULL
n'est pas vrai.La nécessité est la mère de l'invention.
la source
Juste un ajout à d'autres réponses merveilleuses:
la source
Si vous recherchez une expression retournant true pour deux NULL, vous pouvez utiliser:
Il est utile si vous souhaitez répliquer des données d'une table à une autre.
la source
Le test d'égalité, par exemple, dans une instruction case clause when, peut être modifié de
à
Si je veux traiter les espaces et les chaînes vides comme égaux à NULL, j'utilise souvent également un test d'égalité comme:
la source