web-dev-qa-db-fra.com

Paramètre null de procédure stockée dans la clause where

Je veux utiliser un paramètre dans la clause where uniquement si sa valeur est fournie par un ensemble de données fortement typé, c'est ce que j'essaie en ce moment, j'obtiens de bons résultats lorsque je fournis parameter3 et aucun résultat lorsque je ne donne pas sa valeur.

Ce que je désire, c'est quand je ne donne aucune valeur à parameter3, il ne doit pas l'utiliser dans la requête, car sa valeur est nulle et je veux voir tous les résultats dans la requête, pas where Paramerter3 = null ceux:

ALTER procedure [dbo].[GetData]
(
    @Parameter1 varchar(256),
    @Parameter2 varchar(256),
    @Parameter3 int = null
)
AS

SELECT
    *
FROM
    Table1
WHERE
    Table1.URL LIKE '%' + @Parameter1 + '%' 
    AND Table1.ID = @Parameter2
    AND (@Parameter3 IS NULL OR Table1.ID2 = @Parameter3)
ORDER BY
    Table1.Title

Edit: J'ai essayé la réponse de Thomas et exécuté comme ceci:

EXEC @return_value = [dbo].[GetData]
                              @Parameter1 = N'asda',
                              @Parameter2 = N'asda',
                              @Parameter3 = null

SELECT  'Return Value' = @return_value
GO

J'ai également mis à jour la procédure stockée comme Thomas l'a dit.

5
Mathematics
SELECT *
FROM Table1
WHERE Table1.URL LIKE '%' + @Parameter1 + '%' AND Table1.ID = @Parameter2
AND 
(
    @Parameter3 is null 
    or Table1.ID2 = @Parameter3
);

Jetez un œil à l'exemple ci-dessus. Si vous modifiez votre clause AND en une clause imbriquée OR spécifiant votre expression initiale ainsi que @Parameter3 is null. Cela exigera alors que l'expression imbriquée soit vraie si @ Parameter3 est NULL.

14
Thomas Stringer

J'ai toujours été fan d'une approche SQL dynamique pour ce type de problème. Je trouve qu'il fournit l'équilibre optimal entre la complexité et le plan de requête de qualité.

Dans le code suivant, je définis une requête de base qui fait tout ce qu'il faudrait faire et ensuite j'ajoute uniquement les filtres si le paramètre fourni n'est pas nul.

CREATE PROCEDURE [dbo].[GetData]
(
    @Parameter1 varchar(256),
    @Parameter2 varchar(256),
    @Parameter3 int = null
)
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE 
        @BaseQuery nvarchar(max) = N'SELECT T.* FROM dbo.Table1 AS T'
    ,   @ParamList nvarchar(max) = N'@p1 varchar(256), @p2 varchar(256), @p3 int'
    ,   @WhereClause nvarchar(max) = ' WHERE 1=1';

    IF @Parameter1 IS NOT NULL
    BEGIN
        SET @WhereClause = @WhereClause + ' AND T.Url = @p1';
    END

    IF @Parameter2 IS NOT NULL
    BEGIN
        SET @WhereClause = @WhereClause + ' AND T.ID = @p2';
    END

    IF @Parameter3 IS NOT NULL
    BEGIN
        SET @WhereClause = @WhereClause + ' AND T.ID2 = @p3';
    END

    SET @BaseQuery = @BaseQuery + @WhereClause;

    EXECUTE sp_executesql @BaseQuery, @ParamList, @p1 = @Parameter1, @p2 = @Parameter2, @p3 = @Parameter3;
END
12
billinkc

Cela peut être beaucoup plus simple:

SELECT *
FROM Table1
WHERE Table1.URL LIKE '%' + @Parameter1 + '%' AND Table1.ID = @Parameter2
  AND Table1.ID2 = ISNULL(@Parameter3, Table1.ID2)

Remarque: Je n'ai pas vu le commentaire de ConcernedOfTunbridgeWells lorsque j'ai écrit la réponse. J'ai supprimé ma réponse quand je l'ai découvert. Mais à la deuxième pensée, je pourrais simplement le garder et espérer que cela puisse aider les autres. "Où @parameter est nul ou ..." n'a pas de sens, bien que cela puisse fonctionner. L'utilisation de SQL dynamique est exagérée. J'utilise assez souvent le code suivant pour MS SQL et Sybase pour vérifier si un paramètre est nul ou vide:

SELECT * 
FROM tblName 
WHERE [ColumnName] = ISNULL(NULLIF(@parameter, ''), [ColumnName])
  AND ('something else here')
0
Weihui Guo