2010-12-15 55 views
17

J'ai une table qui a une colonne de valeurs qui peut être rowTypeID = (1,2,3, ou null). Je voudrais écrire une requête qui renvoie n'importe quelle ligne qui n'a pas une valeur de 3 dedans. Dans cet exemple, je veux toutes les lignes NULL avec toutes les lignes 1,2 Je ne veux pas de lignes avec la valeur de 3Retour SQL Server Les lignes qui ne sont pas égales <> à une valeur et NULL

Définir ANSI null ON est actuellement défini pour la base de données.

Je suis curieux de savoir pourquoi je ne peux pas écrire

select * from myTable where myCol <> 3 

Cette requête ne renvoie aucune ligne qui ont NULL dans la colonne MyCol

Je dois écrire

select * from my Table where myCol <> 3 or myCol Is NULL 

Dois-je toujours inclure l'IS NULL ou puis-je le configurer de sorte qu'une clause where myCol <> 3 retournera les lignes qui ont la valeur Null pour ma colonne

+13

C'est la façon dont fonctionne NULL, toute comparaison avec elle est faux sauf pour IS NULL et IS NOT NULL – kurosch

+0

@kurosch: Stricly suivant votre ligne, NULL = NULL retournerait aussi faux, puisqu'il s'agit d'une comparaison? – Marcel

+2

@Marcel: oui, NULL = NULL est toujours faux, et que la matière est donc NULL <> NULL :-) – kurosch

Répondre

14

Je pense que votre approche est très bien:

SELECT * 
FROM MyTable 
WHERE myCol <> 3 OR myCol IS NULL 

Puisque vous demandez des alternatives, une autre façon de le faire est de rendre votre colonne NOT NULL et mémoriser une autre (otherwised utilisé) valeur dans la base de données au lieu de NULL - par exemple -1. Alors l'expression myCol <> 3 correspondra à votre faux- NULL comme il le ferait avec n'importe quelle autre valeur.

SELECT * 
FROM MyTable 
WHERE myCol <> 3 

Cependant en général, je recommande pas d'utiliser cette approche. La façon dont vous le faites déjà est la bonne façon.

En outre, il pourrait être utile de mentionner que plusieurs autres bases de données prennent en charge IS DISTINCT FROM qui fait exactement ce que vous voulez:

SELECT * 
FROM MyTable 
WHERE myCol IS DISTINCT FROM 3 

MySQL a NULL-safe equal qui peut également être utilisé à cette fin:

SELECT * 
FROM MyTable 
WHERE NOT myCol <=> 3 

Malheureusement, SQL Server ne prend encore en charge aucune de ces syntaxes.

+0

Veuillez upvote cette fonctionnalité ISO sur le site MS, "DISTINCT PREDICATE": https://connect.microsoft.com/SQLServer/feedback/details/286422/add-language-and-optimizer-support-for-iso-distinct-predicate – montewhizdoh

2

Chaque fois que vous testez une valeur, toutes les valeurs NULL sont omises. Après tout, vous testez si la valeur d'une colonne passe certains critères et que NULL est et non une valeur.

3

Vous devez gérer les valeurs NULL d'une manière ou d'une autre, car les expressions impliquant NULLevaluate to Unknown. Si vous voulez, vous pouvez le faire à la place:

select * 
from MyTable 
where isnull(MyColumn, -1) <> 3 

Mais cela implique un nombre magique (-1), et est sans doute moins lisible que le test original pour IS NULL.

Modifier: et, comme le souligne SQLMenace, n'est pas SARGable.

+3

pas sargable ... – SQLMenace

+0

select * de MyTable où isnull (MaColonne, 3) = 3 – nothrow

+0

@ SQLMenace: bon point, sera également pire - je ne recommande pas ma suggestion. – RedFilter

0

parce que vous ne pouvez pas comparer la valeur NULL à rien d'autre, NULL est même pas égal à NULL

DECLARE @i INT 
DECLARE @i2 INT 

SELECT @i = NULL, @i2 = NULL 

IF @i = @i2 
PRINT 'equal' 
ELSE 
PRINT 'not equal' 
1

Dois-je toujours inclure la IS NULL ou puis-je le configurer de sorte une clause where myCol <> 3 retournera les lignes qui ont la valeur Null pour mon Col?

Vous toujours, toujours, ont toujours inclure is null.

Parce que 3 ne correspond pas Non/applicable et n'est pas égal à inconnu.