J'ai la requête suivante (serveur SQL):
WHERE (@UserId IS NULL OR userId = @UserId)
Mon problème est que si @UserId est nul, la requête ne sera pas évaluée correctement. p>
Comment puis-je écrire cette requête pour évaluer correctement si la variable est nulle ou non?
MODIFIER:
Il y a eu de nombreuses suggestions pour utiliser les éléments suivants:
DECLARE @UserId INT; SET @UserId = //... set by dynamic variable SELECT * FROM Users WHERE userId = @UserId
OU similaire.
Dans ce cas, s'il y a une table de 3 entrées, avec userId de 1,2 et 3 la variable '@UserId 'IS NULL, cette requête renverra les 3 entrées. Ce que j'en ai réellement besoin pour renvoyer, ce n'est aucune entrée, car aucune d'entre elles n'a un userId NULL
5 Réponses :
Après avoir lu la modification, je pense que vous voulez que votre requête ressemble à
SELECT *
FROM Users
WHERE userId = @UserId OR( userId is null and @UserId is null)
Modifier:
Comme indiqué par Gordon Linoff & Larnu que la requête ci-dessus ne sera pas bonne en termes de performances car la requête est "non SARGable", pour de meilleures performances, la même requête peut être écrite comme
SELECT * FROM Users WHERE COALESCE(userId ,0) = COALESCE(@UserId,0)
Utilisez COALESCE avant ISNULL. De nombreuses raisons, la principale à mon avis est que COALESCE est la norme ANSI, ISNULL ne l'est pas. Quelques discussions complémentaires ici: stackoverflow.com/questions/7408893/… ou blogs.msdn.microsoft.com/sqltips/2008/06/26/...
Merci @ChrisCarroll, je vais parcourir le lien, mais j'avais l'impression que pour une seule condition, la correspondance est nulle, c'est mieux.
Je ne supporte pas COALESCE () dans ce but. Je fais des hypothèses sur les valeurs des données.
Cela rend également la requête non SARGable; ce qui signifie que les performances seront moins bonnes et ne feront qu'empirer à mesure que la table Users grandira.
@GordonLinoff, merci de me l'avoir fait savoir, j'ai mis à jour la réponse de manière appropriée.
@Larnu, merci pour les commentaires, j'ai mis à jour la réponse de manière appropriée.
utilisez coalesce
SELECT * FROM Users WHERE userId = coalesce(@UserId,val)
Vous pouvez à la place simplifier la logique booléenne:
WHERE (@UserId IS NULL OR userId = @UserId)
ai-je raison de dire que si '@UserId' est nul, cela ignorera complètement cette clause where?
Vous devez utiliser un OR:
SELECT * FROM Users WHERE UserID = @UserID OR (UserID IS NULL AND @UserID IS NULL);
Ceci, cependant, pourrait bien avoir des problèmes de performances (graves) si vous écrivez ceci dans une procédure stockée , en réutilisant beaucoup ce code ou en ajoutant plus de paramètres NULL. Si tel est le cas, incluez OPTION (RECOMPILE) dans votre requête afin que le plan de requête soit généré à chaque exécution. Cela arrêtera le moteur de données d'utiliser les plans de requête générés qui avaient un ensemble différent de paramètres NULL .
Edit: L'OP n'était pas clair sur leur question. Ils ne veulent pas passer la valeur NULL pour @UserID et renvoyer toutes les lignes, ils veulent passer NULL et obtenir les lignes où UserID a une valeur de NULL . Ce serait:
DECLARE @UserId INT; SET @UserId = //... set by dynamic variable SELECT * FROM Users WHERE (userId = @UserId OR @UserId IS NULL);
ai-je raison de dire que si '@UserId' est nul, cela ignorera complètement cette clause where?
Il n'ignore pas le WHERE no @Alex, cependant, la partie @UserId IS NULL sera évaluée à TRUE si @UserID a une valeur de NULL . Comme userId = @UserId OR @UserId IS NULL doit être évalué à TRUE, toutes les lignes seraient renvoyées lorsque @UserID a une valeur de NULL .
s'il y a une table de 3 entrées, avec userId de 1,2 et 3 la variable '@UserId' EST NULL, ai-je raison de dire que les 3 lignes seraient retournées par cette clause where?
Pourquoi ne testez-vous pas @Alex? La syntaxe ici est également assez simple; y a-t-il une partie spécifique que vous ne comprenez pas? (J'ai seulement ajouté OR et IS NULL , alors avec lequel de ceux-ci avez-vous des problèmes?)
Mes excuses, j'aurais dû le faire. Je l'ai maintenant exécuté et c'est le cas que cela ramènera tous les enregistrements. Je n'ai besoin que de ramener des enregistrements où userId est nul lorsque '@UserId' est nul
Ce n'était pas clair dans votre requête, @Alex, comme vous pouvez le voir, la plupart des réponses ont supposé le contraire ... Mis à jour.
Essayez ceci
DECLARE @UserId INT; SET @UserId = //... set by dynamic variable SELECT * FROM Users WHERE userId= (case when @UserId is null then userId else @UserId end)
Double possible de MySQL: sélection des lignes où une colonne est nulle