Quelqu'un pourrait-il expliquer le comportement suivant en SQL?
SELECT * FROM MyTable WHERE MyColumn != NULL (0 Results)
SELECT * FROM MyTable WHERE MyColumn <> NULL (0 Results)
SELECT * FROM MyTable WHERE MyColumn IS NOT NULL (568 Results)
Quelqu'un pourrait-il expliquer le comportement suivant en SQL?
SELECT * FROM MyTable WHERE MyColumn != NULL (0 Results)
SELECT * FROM MyTable WHERE MyColumn <> NULL (0 Results)
SELECT * FROM MyTable WHERE MyColumn IS NOT NULL (568 Results)
Réponses:
<>
est le standard SQL-92; !=
est son équivalent. Les deux évaluent les valeurs, ce qui NULL
n'est pas - NULL
est un espace réservé pour dire qu'il n'y a pas de valeur.
C'est pourquoi vous ne pouvez utiliser IS NULL
/ IS NOT NULL
comme prédicats que pour de telles situations.
Ce comportement n'est pas spécifique à SQL Server. Tous les dialectes SQL conformes aux normes fonctionnent de la même manière.
Remarque : Pour comparer si votre valeur n'est pas nulle , vous utilisez IS NOT NULL
, tandis que pour comparer avec une valeur non nulle , vous utilisez <> 'YOUR_VALUE'
. Je ne peux pas dire si ma valeur est égale ou non à NULL, mais je peux dire si ma valeur est NULL ou NOT NULL. Je peux comparer si ma valeur est autre que NULL.
!=
avant ~ 9i si je comprends bien, ce qui a apporté beaucoup de syntaxe ANSI-92. Ma conviction est que MySQL est similaire, démarrant le support en 4.x.
!=
aurait pu être inclus dans une spécification ultérieure comme alternative à <>
. Je n'ai pas mes mains sur de nouvelles spécifications, donc je ne peux pas en être sûr.
WHERE MyColumn != NULL
ou WHERE MyColumn = NULL
déterministe? Ou en d'autres termes, est-il garanti de toujours retourner 0 ligne, peu importe si elle MyColumn
peut être annulée ou non dans la base de données?
!=
n'évalue que les valeurs, faire quelque chose comme WHERE MyColumn != 'somevalue'
ne retournera pas les enregistrements NULL.
NULL n'a pas de valeur et ne peut donc pas être comparé à l'aide des opérateurs de valeur scalaire.
En d'autres termes, aucune valeur ne peut jamais être égale (ou non égale) à NULL car NULL n'a pas de valeur.
Par conséquent, SQL a des prédicats IS NULL et IS NOT NULL spéciaux pour traiter NULL.
'a' != null
PAS avoir retourné de valeur ( true
/ 1
) est contre-intuitif et me rattrape de temps en temps! J'aurais pensé "une certaine valeur par rapport à aucune valeur" serait toujours "pas égal", mais peut-être que c'est juste moi?!?
SELECT * FROM MyTable WHERE coalesce(MyColumn, 'x') <> 'x'
attribuer une constante s'il s'agit d'une valeur NULL, à condition de donner un type de données approprié pour la valeur sentinelle x (dans ce cas, une chaîne / caractère). Il s'agit de la syntaxe TSQL mais Oracle et d'autres moteurs ont des fonctionnalités similaires.
Notez que ce comportement est le comportement par défaut (ANSI).
Si vous:
SET ANSI_NULLS OFF
http://msdn.microsoft.com/en-us/library/ms188048.aspx
Vous obtiendrez des résultats différents.
SET ANSI_NULLS OFF
va apparemment disparaître à l'avenir ...
create unique index UK_MyTable on MyTable (Column) where Column is not null
): msdn.microsoft.com/en-us/library/cc280372.aspx
SET ANSI_NULLS
est désactivé, les opérateurs de comparaison Égaux (=) et Non égaux à (<>) ne suivent pas la norme ISO. Une instruction SELECT qui utilise WHERE column_name = NULL
renvoie les lignes qui ont des valeurs nulles dans nom_colonne. Une instruction SELECT qui utilise WHERE column_name <> NULL
renvoie les lignes qui ont des valeurs non nulles dans la colonne. En outre, une instruction SELECT qui utilise WHERE column_name <> XYZ_value
renvoie toutes les lignes qui ne sont pas XYZ_value et qui ne sont pas NULL. À mon humble avis, cette dernière déclaration semble un peu étrange dans son exclusion des null des résultats!
En SQL, tout ce que vous évaluez / calculez avec des NULL
résultats dans INCONNU
C'est pourquoi SELECT * FROM MyTable WHERE MyColumn != NULL
ou SELECT * FROM MyTable WHERE MyColumn <> NULL
vous donne 0 résultats.
Pour vérifier les NULL
valeurs, la fonction isNull est fournie.
De plus, vous pouvez utiliser l' IS
opérateur comme vous l'avez utilisé dans la troisième requête.
J'espère que cela t'aides.
Le seul test pour NULL est IS NULL ou IS NOT NULL. Tester l'égalité est absurde car, par définition, on ne sait pas quelle est la valeur.
Voici un article wikipedia à lire:
Nous utilisons
SELECT * FROM MyTable WHERE ISNULL(MyColumn, ' ') = ' ';
pour renvoyer toutes les lignes où MyColumn est NULL ou toutes les lignes où MyColumn est une chaîne vide. Pour de nombreux "utilisateurs finaux", le problème NULL vs chaîne vide est une distinction sans besoin ni point de confusion.
Je ne vois tout simplement pas la raison fonctionnelle et transparente pour que les valeurs nulles ne soient pas comparables à d'autres valeurs ou à d'autres valeurs nulles, car nous pouvons clairement les comparer et dire qu'elles sont identiques ou non dans notre contexte. C'est marrant. Juste à cause de certaines conclusions logiques et de cohérence, nous devons constamment nous en préoccuper. Il n'est pas fonctionnel, le rend plus fonctionnel et laisse aux philosophes et aux scientifiques le soin de conclure s'il est cohérent ou non et détient-il une «logique universelle». :) Quelqu'un peut dire que c'est à cause des index ou de quelque chose d'autre, je doute que ces choses ne puissent pas être faites pour prendre en charge les valeurs nulles comme les valeurs. C'est la même chose que de comparer deux verres vides, l'un est un verre de vigne et l'autre est un verre de bière, nous ne comparons pas les types d'objets mais les valeurs qu'ils contiennent, de la même manière que vous pourriez comparer int et varchar, avec null it ' s encore plus facile, ce n'est rien et ce que deux néant ont en commun, ils sont les mêmes, clairement comparables par moi et par tous ceux qui écrivent sql, car nous brisons constamment cette logique en les comparant de manière étrange en raison de certaines normes ANSI. Pourquoi ne pas utiliser la puissance informatique pour le faire pour nous et je doute que cela ralentisse les choses si tout ce qui est lié est construit dans cet esprit. "Ce n'est pas nul c'est rien", ce n'est pas Apple c'est apfel, allez ... Fonctionnellement c'est ton ami et il y a aussi de la logique ici. En fin de compte, la seule chose qui compte est la fonctionnalité et l'utilisation de null de cette manière apporte plus ou moins de fonctionnalités et de facilité d'utilisation. Est-ce plus utile? parce que nous brisons constamment cette logique en les comparant de manière étrange à cause de certaines normes ANSI. Pourquoi ne pas utiliser la puissance de l'ordinateur pour le faire pour nous et je doute que cela ralentisse les choses si tout ce qui est lié est construit dans cet esprit. "Ce n'est pas nul c'est rien", ce n'est pas Apple c'est apfel, allez ... Fonctionnellement c'est ton ami et il y a aussi de la logique ici. En fin de compte, la seule chose qui compte est la fonctionnalité et l'utilisation de null de cette manière apporte plus ou moins de fonctionnalités et de facilité d'utilisation. Est-ce plus utile? parce que nous brisons constamment cette logique en les comparant de manière étrange à cause de certaines normes ANSI. Pourquoi ne pas utiliser la puissance de l'ordinateur pour le faire pour nous et je doute que cela ralentisse les choses si tout ce qui est lié est construit dans cet esprit. "Ce n'est pas nul c'est rien", ce n'est pas Apple c'est apfel, allez ... Fonctionnellement c'est ton ami et il y a aussi de la logique ici. En fin de compte, la seule chose qui compte est la fonctionnalité et l'utilisation de null de cette manière apporte plus ou moins de fonctionnalités et de facilité d'utilisation. Est-ce plus utile? s pas apple c'est apfel, allez ... Fonctionnellement est ton ami et il y a aussi de la logique ici. En fin de compte, la seule chose qui compte est la fonctionnalité et l'utilisation de null de cette manière apporte plus ou moins de fonctionnalités et de facilité d'utilisation. Est-ce plus utile? s pas apple c'est apfel, allez ... Fonctionnellement est ton ami et il y a aussi de la logique ici. En fin de compte, la seule chose qui compte est la fonctionnalité et l'utilisation de null de cette manière apporte plus ou moins de fonctionnalités et de facilité d'utilisation. Est-ce plus utile?
Considérez ce code:
SELECT CASE WHEN NOT (1 = null or (1 is null and null is null)) THEN 1 ELSE 0 end
Combien d'entre vous savent ce que ce code renverra? Avec ou sans NOT, il renvoie 0. Pour moi, ce n'est pas fonctionnel et c'est déroutant. En c #, tout est comme il se doit, les opérations de comparaison renvoient de la valeur, logiquement cela produit aussi de la valeur, car si ce n'est pas le cas, il n'y a rien à comparer (sauf. Rien :)). Ils ont juste "dit": n'importe quoi par rapport à null "renvoie" 0 et cela crée de nombreuses solutions de contournement et des maux de tête.
C'est le code qui m'a amené ici:
where a != b OR (a is null and b IS not null) OR (a IS not null and b IS null)
J'ai juste besoin de comparer si deux champs (où) ont des valeurs différentes, je pourrais utiliser la fonction, mais ...
NULL Ne peut être comparé à aucune valeur à l'aide des opérateurs de comparaison. NULL = NULL est faux. Null n'est pas une valeur. L'opérateur IS est spécialement conçu pour gérer les comparaisons NULL.
null = null
où l'on pourrait utiliser 1=0
dans une requête ad hoc. Et s'ils se plaignent, je le change en null != null
:)
Vieille question, mais ce qui suit pourrait offrir plus de détails.
null
ne représente aucune valeur ou une valeur inconnue. Il ne précise pas pourquoi il n'y a pas de valeur, ce qui peut conduire à une certaine ambiguïté.
Supposons que vous exécutez une requête comme celle-ci:
SELECT *
FROM orders
WHERE delivered=ordered;
c'est-à-dire que vous recherchez des lignes où le ordered
etdelivered
dates sont identiques.
Que faut-il attendre lorsqu'une ou les deux colonnes sont nulles?
Parce qu'au moins une des dates est inconnue, vous ne pouvez pas vous attendre à dire que les 2 dates sont les mêmes. C'est également le cas lorsque les deux dates sont inconnues: comment peuvent-elles être les mêmes si nous ne savons même pas ce qu'elles sont?
Pour cette raison, toute expression considérée null
comme une valeur doit échouer. Dans ce cas, il ne correspondra pas. C'est également le cas si vous essayez ce qui suit:
SELECT *
FROM orders
WHERE delivered<>ordered;
Encore une fois, comment pouvons-nous dire que deux valeurs ne sont pas identiques si nous ne savons pas ce qu'elles sont.
SQL a un test spécifique pour les valeurs manquantes:
IS NULL
Plus précisément, il ne s'agit pas de comparer des valeurs, mais plutôt de rechercher des valeurs manquantes .
Enfin, en ce qui concerne l' !=
opérateur, pour autant que je sache, il ne figure en fait dans aucune des normes, mais il est très largement soutenu. Il a été ajouté pour que les programmeurs de certaines langues se sentent plus à l'aise. Franchement, si un programmeur a du mal à se souvenir de la langue qu'il utilise, il commence mal.
NULL
nous voulons dire que nous comparons une valeur à «avoir unNULL
valeur», et non pas la valeur à «la valeur indéterminée que la sous NULL
- couche « a », mais que nous ne savons pas ", ce que nous ne pourrons évidemment jamais savoir. Cela faciliterait vraiment les choses.
IS NULL
soit beaucoup plus ardue que l'écriture = NULL
. Je pense qu'il serait plus cohérent s'il WHERE columnA = columnB
a la même interprétation que WHERE columnA = NULL
, plutôt que de traiter ce dernier comme un cas spécial. N'oubliez pas que ce NULL
n'est pas une valeur. Dans les langages de programmation où il est légitime de le tester, variable == null
c'est parce qu'il null
a une signification différente; il ne représente pas quelque chose d'inconnu, mais une réinitialisation délibérée d'une valeur. Ce n'est pas le cas avec SQL.
IS NULL
ET =NULL
dans votre dernier exemple. Mais jetez un œil au dernier de Hover. Je suis fatigué de le vivre encore et encore, d'avoir à faire des tonnes de choses inutiles? vérification supplémentaire ...
Je voudrais suggérer ce code que j'ai fait pour trouver s'il y a un changement dans une valeur,
i
étant la nouvelle valeur et d
étant l'ancienne (bien que l'ordre n'ait pas d'importance). D'ailleurs, un changement de valeur à null ou vice versa est un changement mais de null à null ne l'est pas (bien sûr, de la valeur à une autre valeur est un changement mais de la valeur à la même chose ne l'est pas).
CREATE FUNCTION [dbo].[ufn_equal_with_nulls]
(
@i sql_variant,
@d sql_variant
)
RETURNS bit
AS
BEGIN
DECLARE @in bit = 0, @dn bit = 0
if @i is null set @in = 1
if @d is null set @dn = 1
if @in <> @dn
return 0
if @in = 1 and @dn = 1
return 1
if @in = 0 and @dn = 0 and @i = @d
return 1
return 0
END
Pour utiliser cette fonction, vous pouvez
declare @tmp table (a int, b int)
insert into @tmp values
(1,1),
(1,2),
(1,null),
(null,1),
(null,null)
---- in select ----
select *, [dbo].[ufn_equal_with_nulls](a,b) as [=] from @tmp
---- where equal ----
select *,'equal' as [Predicate] from @tmp where [dbo].[ufn_equal_with_nulls](a,b) = 1
---- where not equal ----
select *,'not equal' as [Predicate] from @tmp where [dbo].[ufn_equal_with_nulls](a,b) = 0
Les résultats sont:
---- in select ----
a b =
1 1 1
1 2 0
1 NULL 0
NULL 1 0
NULL NULL 1
---- where equal ----
1 1 equal
NULL NULL equal
---- where not equal ----
1 2 not equal
1 NULL not equal
NULL 1 not equal
L'utilisation de sql_variant le rend compatible pour une variété de types
NULL n'est rien ... il est inconnu. NULL ne vaut rien. C'est pourquoi vous devez utiliser la phrase magique IS NULL au lieu de = NULL dans vos requêtes SQL
Vous pouvez vous référer à ceci: http://weblogs.sqlteam.com/markc/archive/2009/06/08/60929.aspx
<>
que c'est dans la spécification 92, mais la plupart des fournisseurs prennent en charge!=
et / ou il est inclus dans une spécification ultérieure comme 99 ou 03.