10
votes

Valeurs SQL et NULL dans l'endroit où la clause

Donc, j'ai une requête simple qui renvoie une liste de produits xxx

ce retour xxx

ce qui est correct, donc je voulais Seuls les produits dont la catégorieId n'est pas '00000000-0000-0000-0000-00000000000000', j'ai donc xxx

mais cela ne renvoie aucun résultat. J'ai donc changé la requête en xxx

qui retourne résultat attendu xxx

peut-il m'expliquer ce comportement? MS SQL Server 2008


3 commentaires

L'article Wiki est tout à fait bien pour expliquer NULL - EN.Wikipedia.org/wiki/Null_% 28SQL% 29


@Russ Cam - vous auriez dû poster cela comme une réponse ...


Je sentais que c'était plus d'une réponse lmgtfy :)


6 Réponses :


9
votes

4 commentaires

Soyez prudent, définissez ANSI_NULLS sur OFF Réduire les performances et augmentera les lectures logiques. Le tourner sur affecte le plan de requête.


@ Vol7ron a vraiment mérité un bowvote ?! Que v durs pour quelle est une réponse correcte. Si vous jugez honnêtement que cela garantit un bowvote, assez juste mais je suis impatient et pas un vote honnête


Quel méritait un bowvote? Je ne pense pas que cela mérite un baissier ou un hausse. C'est une réponse. Je n'irais pas si loin pour dire que c'est "correct" non plus. La mise en œuvre de cela prendra une performance touchée, mais plus important encore, il n'est techniquement pas standard SQL, au moment où vous mettez en œuvre cela, vous échouez d'ISO. L'une des meilleures choses à propos de SQL est la possibilité d'aller de la plate-forme à la plate-forme, vous donnez cela ici. coalesce est une meilleure solution. Comme je l'ai dit, si vous êtes inquiet de l'impact de la performance, indice que le champ avec la fonction, sinon nettoyez les données sous-jacentes.


AVERTISSEMENT: ANSI_NULLULES DEVRAIT ÊTRE AVOIDÉE, MS DITES NON ET SON DEPRÉCORATION SONT A LA MAIN: msdn.microsoft.com/en-us/library/ms188048.aspx



0
votes

null obtient un traitement spécial. Vous devez tester explicitement pour NULL. Voir http://msdn.microsoft.com/en-us/library/ms188795. ASPX


0 commentaires

1
votes

Regardez ceci:

1=1        --true
1=0        --false
null=null  --false
null=1     --false

1<>1       --false
1<>0       --true
null<>null --false
null<>1    --false    <<<--why you don't get the row with: AND (CategoryID <> '00000000-0000-0000-0000-000000000000') 


2 commentaires

Techniquement, SQL utilise un système de logique à trois évaluations, de sorte que toutes vos comparaisons avec un rendement null inconnu plutôt que false. Voir: SQL et le piège de la logique à trois valeurs .


Appelez-le false ou inconnu , cela n'a pas vraiment d'importance, car la ligne n'est pas incluse dans le jeu de résultats, ce qui est la question de la question.



2
votes

Fondamentalement, une null est l'absence de toute valeur em>. Tellement essayer de comparer la valeur null dans la catégorieid à une valeur de varchar dans la requête entraînera toujours une fausse évaluation.

Vous voudrez peut-être essayer d'utiliser la fonction Coalesce, quelque chose comme: P>

SELECT     ModelId, CategoryID 
FROM       Products 
WHERE      (ModelId = '010-00749-01')  
AND        ( COALESCE( CategoryID, '' ) <> '00000000-0000-0000-0000-000000000000' ) 


2 commentaires

Faites attention à cette approche, car la regroupement pourrait entraîner un plan d'exécution moins optimal en empêchant un indice de recherche sur cette colonne.


Ada est correct, la coalesse a un effet sur le plan d'exécution. Modifiera ma réponse à inclure.



0
votes

Vous pouvez essayer d'utiliser la fonction coalesce pour définir une valeur par défaut pour les champs null : xxx

Je pense que le problème Réside dans votre compréhension de null qui signifie fondamentalement "rien". Vous ne pouvez rien comparer à rien à rien, beaucoup comme vous ne pouvez pas diviser un nombre par 0. Ce n'est que des règles de mathématiques / science.

EDIT: Comme l'a souligné ADA, cela pourrait provoquer un champ indexé de ne plus utiliser d'index.

solution:

  • Vous pouvez créer un index à l'aide de la fonction Coalesce: p.ex. créer index ... coalesce (champ)
  • Vous pouvez ajouter un NON NULL contrainte pour empêcher que les nulles apparaissent jamais
  • une norme de mine de facto consiste à toujours affecter des valeurs par défaut et n'autorise jamais NULLS

2 commentaires

Faites attention à cette approche, car la regroupement pourrait entraîner un plan d'exécution moins optimal en empêchant un indice de recherche sur cette colonne.


Cela pourrait être vrai, cependant, vous pouvez créer un index comme coalesce (champ) ou ajoutez une contrainte NON NULL pour empêcher les NULLS d'apparaître jamais. Une norme de mine de facto consiste à toujours affecter des valeurs par défaut et n'autorise jamais les nulls.



2
votes

En général, vous devez vous rappeler que NULL signifie généralement inconnu. Cela signifie que si vous dites CatégorieId <> '00000000000000000000-0000-00000000000000' Vous devez supposer que la requête ne renvoie que les valeurs qu'elle sait satisfaire à vos critères. Comme il existe un résultat nul (inconnu), il ne sait pas que si cet enregistrement répond à vos critères et ne sera donc pas retourné dans l'ensemble de données.


1 commentaires

Bien que les autres réponses contiennent plus de détails, j'aime celui-ci à cause de la simplicité. C'est compréhensible même à une non-technologie, et donc précieux pour les nouveaux développeurs. +1.