J'ai essayé de récupérer des données de ma procédure stockée. @ContactID
est le paramètre d'entrée, où l'utilisateur clique sur le bouton d'affichage de la requête. Donc, si @ContactID
est nul, alors je veux retourner la table entière et quand @ContactID
a une valeur, alors je veux retourner seulement cette ligne spécifique. Merci
DECLARE @ContactID INT = NULL SELECT * FROM Contact C WHERE C.PK_Contact IN (CASE WHEN @ContactID IS NULL THEN (SELECT PK_Contact FROM Contact) ELSE @ContactID END)
Mais j'obtiens cette erreur:
La sous-requête a renvoyé plus d'une valeur. Cela n'est pas autorisé lorsque la sous-requête suit =,! =, ,> = Ou lorsque la sous-requête est utilisée comme expression.
3 Réponses :
Supprimez IN et la sous-requête:
WHERE C.PK_Contact = C.PK_Contact
Ainsi, lorsque @ContactID est NULL
la condition est
declare @ContactID int =null SELECT * FROM Contact C WHERE C.PK_Contact = (CASE WHEN @ContactID IS NULL THEN C.PK_Contact ELSE @ContactID END)
qui est toujours TRUE et cela renverra toutes les lignes.
Pouvez-vous simplement essayer ceci à la place?
-- you should *really* get in the habit of explicitly spelling out which columns you need! -- Don't use "SELECT *" in production code! SELECT * FROM dbo.Contact C WHERE C.PK_Contact = ISNULL(@ContactID, C.PK_Contact)
Si @ContactID
a une valeur spécifique, vous ne renvoyez que les lignes qui correspondent à Valeur de l'ID
. Si @ContactID
est NULL, vous renvoyez toutes les lignes.
@Hrv Vous devez marquer la meilleure réponse pour résoudre votre problème comme accepté. Veuillez choisir l'une des deux réponses.
@Sami oui bien sûr. mais cela donnera popup que je peux accepter la réponse après 3 minutes!
@Hrv. . . C'est la meilleure solution. Il n'utilise que des opérations booléennes de base, plutôt que d'introduire des expressions case
dans la clause where
.
@GordonLinoff et où est le problème avec l'expression de cas qui est un standard? Comment est-ce mieux? Il n'utilise que des opérations booléennes de base Une instruction case utilise-t-elle quelque chose de différent moins efficace?
@forpas. . . Les expressions case
imposent un ordre lors de l'évaluation. C'est la seule expression qui a vraiment une telle contrainte d'ordre. Cela tue à peu près l'optimiseur.
@Hrv prend un certain temps et lisez pourquoi devrait éviter d'utiliser des fonctions comme ISNULL () dans la clause WHERE: blog.sqlauthority.com/2013/03/12/... et mssqltips.com/sqlservertip/1236/... et mssqltips.com/sqlservertutorial/3204/… < / a>
@GordonLinoff Je vois que mon commentaire précédent est supprimé et je ne sais pas pourquoi! Depuis quand les commentaires techniques sont-ils supprimés? Encore une fois: pensez-vous que l'optimiseur est plus heureux avec une fonction qu'avec une instruction CASE? Si oui, en avez-vous la preuve? J'ai posté des liens dans mon commentaire précédent pour prouver pourquoi les fonctions devraient être évitées. En avez-vous pour soutenir ce que vous avez dit?
Vous pouvez également le faire.
+-----+-----+ | id | val | +-----+-----+ | 2 | 55 | +-----+-----+
Structure de la table et exemples de données
DECLARE @input INT = 2 SELECT * FROM mytable WHERE (@input IS NULL OR id = @input)
Quand l'entrée est nulle ...
+-----+-----+ | id | val | +-----+-----+ | 1 | 25 | | 2 | 55 | | 3 | 25 | | 4 | 10 | | 5 | 60 | +-----+-----+
Output
DECLARE @input INT = NULL SELECT * FROM mytable WHERE (@input IS NULL OR id = @input)
Lorsque l'entrée n'est pas nulle ...
CREATE TABLE mytable (id INT, val INT); INSERT INTO mytable VALUES (1,'25'), (2,'55'), (3,'25'), (4,'10'), (5,'60');
Sortie
SELECT * FROM Contact WHERE (@ContactID is null or PK_Contact = @ContactID)
Démo en ligne: https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle> / p>
select PK_Contact from Contact
renvoie tous lesPK_Contact
s de la tableContact
.Quel est le type de données du paramètre
@ContactID
et ce qu'il contient? Utilisez-vous SQL Server 2008 ou 20012? BTW SQL Server 2008 n'est plus pris en charge, vous devriez vraiment mettre à niveauoui donc je veux que WHERE C.PK_Contact IN (renvoyé tous les PK de la table Contact)
@Sami Désolé pour la balise sql-2008 et 12. Je viens de rejoindre le débordement de pile donc je ne sais pas comment poster.