web-dev-qa-db-fra.com

Comment inclure des valeurs nulles lors des comparaisons dans SQL Server?

Donc, fondamentalement, dans SQL Server, un NULL signifie qu'il n'y a pas de valeur et ne peut donc pas être comparé, ce qui renvoie des résultats inattendus.

Par exemple, la requête suivante ne renvoie pas de lignes où la valeur IS NULL mais je le veux:

SELECT *
FROM table
WHERE
  (value != 26)
  AND date IS NULL
  AND last_modified >= '5/21/2014'

Je comprends que je peux faire ce qui suit comme solution de contournement mais sérieusement? Devoir ajouter des parenthèses et vérifier si est nul pour chaque champ à chaque fois que je veux l'inclure? Semble moche, pas intuitif et fou.

SELECT *
FROM table
WHERE
  (value != 26 OR value is null)
  AND date IS NULL
  AND last_modified >= '5/21/2014'

Je veux dire que je sais que NULL n'est pas une valeur et ne peut donc pas être comparé, mais ne pouvez-vous pas en déduire que ce n'est en fait certainement pas 26? Si 26 est quelque chose et NULL n'est rien et rien n'est pas quelque chose, alors NULL n'est pas 26. Cela me semble logique.

Est-ce que quelqu'un sait comment je peux, d'une manière plus propre, inclure des valeurs nulles dans mes résultats lors de l'utilisation de comparaisons sans avoir à inclure une vérification explicite à chaque fois. Désactiver également les valeurs nulles sur mes tables n'est certainement pas une option.

Éditer:

Mon vrai problème de savoir pourquoi je ne veux pas le faire comme je l'ai montré n'a pas été exposé. Alors voilà. J'écris un programme qui vous permet de créer des requêtes sur des tables de base de données et permet à l'utilisateur de créer dynamiquement des filtres et autres qui, essentiellement, à la fin de la journée, construisent une instruction SQL et obtiennent les résultats à afficher pour l'utilisateur. Les champs choisis par l'utilisateur peuvent être n'importe lesquels et/ou tous les champs d'une base de données donnée et si je dois littéralement mettre cette vérification ISNULL sur chaque champ, ce serait vraiment inefficace et rendrait le SQL super laid. Mon programme est indépendant de la définition de la table, ce qui signifie que je me fiche de ce qui se trouve dans votre table et que je ne veux pas savoir quelle est la définition de votre table. Je veux juste que vous choisissiez une table, que vous choisissiez des champs sur lesquels filtrer des égaux, pas des égaux, dans, pas dans, etc., puis cliquez sur un bouton pour afficher les résultats de cette demande.

8
Brian T Hannan

Pour commencer, NULL ne signifie pas "aucune valeur", il signifie "valeur inconnue" dans SQL Server. Il existe un paramètre de session appelé ANSI_NULLS qui pourrait faire en sorte que vos requêtes se comportent comme vous le souhaitez, mais il est obsolète et sera forcé à ON (ce que vous ne semblez pas aimer) dans une future version: http : //msdn.Microsoft.com/en-us/library/ms188048.aspx

Je comprends ce que vous essayez de faire, et pour faire un contrepoint, je vous demanderais si vous avez vu des requêtes générées par des services de reporting ou quelque chose comme Cognos? Si c'est le cas, vous verrez exactement ce que vous décrivez que vous ne voulez pas faire. Pourquoi? Eh bien parce qu'avec un schéma qui autorise les valeurs nulles, c'est la façon de le faire. Je ne dis pas que c'est une idée super géniale et géniale, mais cela fonctionne tout le temps.

Ce que votre concepteur pourrait faire est de vérifier si cette colonne pourrait même être nulle et si oui, la logique appropriée pourrait la modifier et créer la requête correcte. Vous pouvez également avoir des options telles que "Cette colonne peut être nulle, voulez-vous ces valeurs?". Je ne connais pas la fin de jeu en soi et écrire votre propre outil de requête dynamique est tout à fait la tâche lorsque les consistances logiques sont toutes prises en compte (comme celle-ci).

Je continuerais à faire une vérification nulle explicite sur les colonnes qui pourraient éventuellement être nulles, bien sûr, cela ne semble pas le meilleur, mais cela fonctionne tout le temps.

L'option ANSI_NULL set fonctionnera pour l'instant, mais ce n'est PAS une bonne idée, surtout si vous ne contrôlez pas l'environnement.En outre, elle sera forcée à être activée ultérieurement et provoquera des erreurs où vous devrez de toute façon réécrire la logique de votre application. C'est ainsi que SQL Server fonctionne avec les valeurs NULL.

9
Sean Gallardy

Le problème NULL est un problème épineux avec SQL. C'est essentiellement une erreur qui est maintenant gravée dans tous les logiciels SQL de la planète. Nous devons y faire face.

value <> 26 or value is null Est un bon moyen d'implémenter cette logique. Il existe d'autres formulations de la même sémantique.

Si vous savez que la valeur n'est jamais -1 (Par exemple), vous pouvez dire ISNULL(value, -1) <> 26. Je ne pense pas que ce soit mieux du point de vue de la lisibilité. Il peut également provoquer des problèmes d'optimisation car ce prédicat peut ne pas être SARGable. value is null est un prédicat SARGable et indexable contrairement à la croyance populaire.

SQL possède l'opérateur IS DINSTINCT FROM Mais T-SQL ne le prend pas en charge. Veuillez prendre une seconde pour voter pour que la demande soit mise en œuvre! Il s'agit d'un problème purement syntaxique. L'optimiseur n'a pas besoin de changer du tout. Il prend déjà en charge cet opérateur en interne.

TL; DR: La façon dont vous le faites en ce moment est la bonne. Vivre avec.

7
usr