2
votes

Serveur SQL où la variable de clause peut être nulle

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 :


1
votes

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)  


6 commentaires

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.



1
votes

utilisez coalesce

SELECT *
FROM Users
WHERE userId = coalesce(@UserId,val)


0 commentaires

0
votes

Vous pouvez à la place simplifier la logique booléenne:

WHERE (@UserId IS NULL OR userId = @UserId)


1 commentaires

ai-je raison de dire que si '@UserId' est nul, cela ignorera complètement cette clause where?



1
votes

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);


6 commentaires

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.



0
votes

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)


0 commentaires