2010-06-22 6 views
2

Je suis sûr que cela a une réponse très simple que je ne trouve pas ... J'ai une hiérarchie simple dans une base de données où chaque ligne a un ParentId. Si ParentId IS NULL, alors c'est un élément racine. J'ai la procédure stockée:Procédure stockée pour gérer le paramètre nul

CREATE PROCEDURE GetByParent @parentId int 
AS BEGIN SELECT * FROM TABLE1 WHERE ParentId = @parentId END 

Il fonctionne très bien si j'envoie un entier, mais si j'envoie NULL il devient ParentId = NULL, qui ne fonctionne pas dans la norme ANSI. Je sais qu'il y a COALESCE(@parentId, ParentId), mais cela retourne toutes les lignes quand @parentId IS NULL. Je peux faire une instruction IF ELSE et copier la requête (une avec = @parentId et l'autre avec IS NULL), mais je suis sûr qu'il y a une meilleure façon.

Répondre

5

Manipulez le cas NULL dans un état séparé:

SELECT * 
FROM TABLE1 
WHERE ParentId = @parentId 
    OR (ParentId IS NULL AND @parentId IS NULL) 
+0

C'est tout ... ça ne me vint pas à l'esprit d'utiliser COALESCE des deux côtés. –

+0

J'ai sorti la version COALESCE et l'ai remplacée par cette version actuelle. Sur une grande table, COALESCE (ParentId) peut provoquer des problèmes de performances en déclenchant une analyse de table. Avec cette version actuelle, le planificateur de requêtes doit toujours utiliser tout index que vous avez sur ParentId. – Toby

+1

Hé, c'est ma ligne;) – laher

1

vous pouvez simplement utiliser une déclaration ou

... WHERE (@parentId IS NULL AND ParentId IS NULL) OR [email protected]

3

En fait, le SI/méthode ELSE est le plus performant court d'utiliser SQL dynamique. En supposant que SQL Server 2005+, vous pouvez utiliser:

DECLARE @SQL NVARCHAR(max) 
    SET @SQL = 'SELECT * FROM TABLE1 WHERE 1=1 ' 

    SET @SQL = CASE 
       WHEN @parentid IS NULL THEN ' AND parentid IS NULL ' 
       ELSE ' AND parentid = @parentid ' 
       END 

BEGIN 

    EXEC sp_executesql @SQL, N'parentid INT', @parentid 

END 

obligatoire SI/AUTRE:

BEGIN 

    IF @parentid IS NULL 
    BEGIN 
    SELECT * FROM TABLE1 WHERE parentid IS NULL 
    END 
    ELSE 
    BEGIN 
    SELECT * FROM TABLE1 WHERE parentid = @parentid 
    END 

END 
+0

Ouais, j'ai pensé à utiliser le SQL dynamique, mais il semblait être exagéré. Je l'ai eu avec le if/else, mais je n'aime pas avoir à tout répéter (colonnes à sélectionner, jointures, etc.). Je ne m'inquiète pas trop de la performance ici car c'est une hiérarchie plutôt petite/plate. –

+1

@Nelson: Les OR sont connus pour leurs faibles performances. –

3

Je fais l'hypothèse que vous n'utilisez pas ids négatives pour parentID.

Si vous utilisez deux instructions isNull, vous pouvez couvrir tous les cas dans une requête:

SELECT * FROM TABLE1 WHERE ISNULL(ParentId,-1) = ISNULL(@parentId,-1) 

De cette façon, lorsque @parentid IS NULL, ne retournera les résultats avec les valeurs NULL, au lieu de toutes les lignes.

Questions connexes