web-dev-qa-db-fra.com

IS NULL contre <> 1 bit SQL

J'ai une petite colonne sur une table dans une base de données SQL Server 2012.

J'essaie de récupérer toutes les lignes où cette colonne de bits est NULL ou NOT TRUE.

Cette requête ne ramène pas ce qu'elle devrait: (retourne 0 lignes)

Select * 
from table 
where bit_column_value <> 1

Cette requête ramène les lignes correctes:

Select * 
from table 
where bit_column_value IS NULL

Maintenant, je serais heureux d'utiliser la deuxième requête, mais mon problème est que, dans une requête similaire pour une autre table, l'inverse de ce qui précède est vrai, où la première méthode fonctionne, mais pas la seconde!

Quelqu'un pourrait-il aider à expliquer quelle est la différence dans ce qui précède? J'ai spécifiquement mis à jour les colonnes de bits pertinentes pour qu'elles soient NULES et cela ne change pas les résultats. (Je pensais qu'il y avait peut-être une différence entre les valeurs "Empty" et Null.

Merci d'avance pour toutes explications.

19
ché

La raison <> ne fonctionne pas, c'est que SQL traite NULL comme inconnu - il ne sait pas ce que NULL est censé signifier, donc il évalue les deux = et <> sur une valeur NULL comme UNKNOWN (qui est traitée comme fausse dans une clause where ou une condition de jointure). Pour plus d'informations, lisez ceci: Pourquoi NULL = NULL est-il évalué à faux dans le serveur SQL .

S'il y a un index dessus, l'utilisation de la fonction ISNULL signifie que l'index ne peut pas être utilisé, donc pour vous assurer que la requête peut utiliser l'index, utilisez simplement OR:

SELECT * 
FROM TableName
WHERE
   bit_column_value IS NULL OR bit_column_value = 0
27
Bennor McCarthy

votre meilleur pari serait d'écrire la requête comme telle:

SELECT
     * 
FROM 
     table 
WHERE 
     ISNULL(bit_column_value, 0) = 0

Cela devrait renvoyer tous les enregistrements NULL et FALSE.

Sans voir la structure et les données de votre table, je ne peux pas vraiment expliquer pourquoi vous obtenez des résultats différents à partir de vos 2 requêtes.

7
SQLGuru

MSDN indique que le type BIT peut stocker les valeurs 0, 1 ou NULL. (Le fait qu'une valeur BIT soit NULL doit être stocké séparément de la valeur binaire elle-même, car les valeurs binaires peuvent être compressées de sorte que 8 valeurs BIT soient stockées dans un octet.)

N'oubliez pas qu'une condition dans une clause WHERE sélectionne une ligne lorsque la condition est VRAIE. Pour la plupart des prédicats binaires (conditions), si vous comparez NULL avec une certaine valeur, le résultat est NULL ou UNKNOWN (pas TRUE). Ainsi, par exemple, si la valeur d'une colonne est NULL, alors column = 0 prend la valeur NULL ou UNKNOWN, tout comme column <> 0.

En regardant vos requêtes:

SELECT * FROM table WHERE bit_column_value <> 1

Où la valeur dans le bit_column_value la colonne est 1, la condition est FALSE donc la ligne n'est pas retournée; où la valeur est 0, la condition est VRAIE donc la ligne est retournée; et lorsque la valeur est NULL, la condition est également NULL ou UNKNOWN, de sorte que la ligne n'est pas renvoyée.

SELECT * FROM table WHERE bit_column_value IS NULL

Selon le standard SQL, les prédicats IS [NOT] NULL) et les prédicats IS [NOT] {TRUE | FALSE | UNKNOWN} associés sont légèrement Le test IS NULL renvoie VRAI si la valeur testée est NULL; sinon, ils renvoient FAUX (et ne renvoient jamais INCONNU). Le IS [NON] Les tests {TRUE | FALSE | UNKNOWN} sont similaires; ils renvoient TRUE si la valeur est du type spécifié et FALSE sinon (pas UNKNOWN). Par exemple:

Column   IS TRUE   IS FALSE   IS UNKNOWN   IS NOT TRUE   IS NOT FALSE   IS NOT UNKNOWN
FALSE    FALSE     TRUE       FALSE        TRUE          FALSE          TRUE
TRUE     TRUE      FALSE      FALSE        FALSE         TRUE           TRUE
NULL     FALSE     FALSE      TRUE         TRUE          TRUE           FALSE

Ainsi, dans votre deuxième requête, seules les lignes où le bit_column_value la valeur est NULL (qui est distincte de 0 et 1) sera sélectionné - pas le VRAI, ni le FAUX.


J'essaie de récupérer toutes les lignes où cette colonne de bits est NULL ou NOT TRUE.

Essayez d'écrire la requête directement à partir de vos spécifications:

  1. SELECT * FROM table WHERE bit_column_value IS NULL OR bit_column_value IS NOT TRUE
  2. SELECT * FROM table WHERE bit_column_value IS NULL OR bit_column_value = FALSE
  3. SELECT * FROM table WHERE bit_column_value IS NULL OR bit_column_value <> TRUE
  4. SELECT * FROM table WHERE bit_column_value IS NOT TRUE

Compte tenu de la table de vérité ci-dessus, la requête 4 donnerait le résultat souhaité - avec la mise en garde majeure que je ne suis pas certain que MS SQL Server prend en charge le IS [NOT] {TRUE | FALSE | UNKNOWN }. A en juger par MSDN sur Prédicats , les prédicats IS [NOT] {TRUE | FALSE | UNKNOWN} ne sont pas pris en charge (mais j'ai peut-être manqué la bonne partie de Si c'est correct, vous devez utiliser l'une des requêtes 2 ou 3.


(Il y a quelques complications supplémentaires avec ces prédicats lorsque la valeur n'est pas une simple colonne mais une valeur de ligne. Cependant, cela n'est pas pertinent pour votre question ou problème; doublement pas car MS SQL Server ne semble pas les prendre en charge.)

2
Jonathan Leffler

Je pense que c'est parce que toutes les données ont des valeurs NULL dans cette colonne. Alors:

Select * 
from table 
where bit_column_value <> 1;

Ne vous donnera pas le résultat. Puisque NULL est inconnu. Et ça:

Select * 
from table 
where bit_column_value IS NULL;

Vous donnera le résultat que vous recherchez.

Mais vous avez une idée fausse de représenter vrai et faux en utilisant le bit type de données.

Vous représentez false comme NULL, 0 est vide et vrai est toute autre valeur. Les types de données bit fonctionnent comme @ IswantoSan expliqué dans sa réponse ; Ce doit être 0 ou 1 ou NULL:

  • 0 est faux,
  • 1 est vrai,
  • NULL est vide.

Par conséquent, pour obtenir:

  • true les valeurs utilisent le where bit_column_value = 1.
  • false les valeurs utilisent le where bit_column_value = 0.
  • NULL ou vide where bit_column_value IS NULL.
  • NULL or not true:où bit_column_value IS NULL ou bit_column_value = 0`.

L'autre chose à noter est que NULL et empty sont deux choses différentes, ce ne sont pas les mêmes. Dans le cas du type de données BIT, vide est NULL et non 0, car 0 est supposé être faux. Mais considérez un type de données de chaîne comme VARCHAR par exemple, puis la chaîne vide '' est totalement différent de la valeur NULL.

1
Mahmoud Gamal

Veuillez vérifier les données de votre table, si elles contiennent une valeur = 0?

type de données SQL Bit ne peut avoir que la valeur 0, 1 ou NULL, si vous insérez une autre valeur, elle est considérée comme 1 (exception: si vous insérez 'False 'il deviendra 0,' True 'deviendra 1).

Par exemple :

insert into t1 values (1),(2),(1),(3),(-1),(0),(NULL),('false'),('true')

Le résultat :

1, 1, 1, 1, 1, 0, NULL, 0, 1

1
Iswanto San