2010-12-29 2 views
0

Je reçois une erreur lorsque j'essaie d'utiliser plusieurs instructions IF. Ceci est l'erreur ...Instructions IF multiples SQL Server 2000

"Msg 156, Niveau 15, État 1, Procédure fnTNAccidentIndicator, Ligne 81 syntaxe incorrecte près du mot-clé 'END'."

C'est la structure de mon code ...

USE SS_TNRecords_Accident 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 

CREATE FUNCTION dbo.fnTNAccidentIndicator 
(
    @inAccidentNumber nvarchar(100), 
    @inIndicatorMode int 
) 
RETURNS nvarchar 
AS 
BEGIN 
    DECLARE @AlcoholInd nvarchar(1) 
    DECLARE @DrugInd nvarchar(1) 
    DECLARE @SpeedInd nvarchar(1) 
    DECLARE @ReturnValue nvarchar(1) 

    SET @AlcoholInd = '1' 
    SET @DrugInd = '2' 
    SET @SpeedInd = '3' 
    SET @ReturnValue = 'N' 

    IF (@inIndicatorMode = @AlcoholInd) 
    BEGIN 
     SELECT AccidentNumber, AlcoholTestResult FROM tblAccidentUnit 
      WHERE AccidentNumber = @inAccidentNumber AND AlcoholTestResult NOT IN('00', '95', '96', '97', '98', '99') 
     UNION 
     SELECT AccidentNumber, AlcoholTestResult FROM tblAccidentOccupant 
      WHERE AccidentNumber = @inAccidentNumber AND AlcoholTestResult NOT IN('00', '95', '96', '97', '98', '99') 
     UNION 
     SELECT AccidentNumber, AlcoholTestResult FROM tblAccidentNonMotorist 
      WHERE AccidentNumber = @inAccidentNumber AND AlcoholTestResult NOT IN('00', '95', '96', '97', '98', '99') 
     IF (@@ROWCOUNT > 0) 
     BEGIN 
      SET @ReturnValue = 'Y' 
     END 
    END 

    IF (@inIndicatorMode = @DrugInd) 
    BEGIN 
     SELECT a.AccidentNumber,'AccidentUnit' AS TableFound, c.PrimaryKey AS TableKeyValue 
      FROM tblAccident a INNER JOIN tblAccidentUnit b 
       ON a.AccidentNumber = b.AccidentNumber INNER JOIN tblAccidentUnitDrug c 
        ON b.PrimaryKey = c.ForeignKey 
       AND a.AccidentNumber = '001' 
      WHERE c.DrugTestResult IN('02', '03', '04', '05', '06', '07', '08', '97', '98')  
      UNION  
      SELECT a.AccidentNumber, 'AccidentOccupant' AS TableFound, c.PrimaryKey AS TableKeyValue 
       FROM tblAccident a INNER JOIN tblAccidentOccupant b 
        ON a.AccidentNumber = b.AccidentNumber INNER JOIN tblAccidentOccupantDrug c 
         ON b.PrimaryKey = c.ForeignKey 
       AND a.AccidentNumber = '001' 
      WHERE c.DrugTestResult IN('02', '03', '04', '05', '06', '07', '08', '97', '98') 
      UNION 
      SELECT a.AccidentNumber, 'AccidentNonMotorist' AS TableFound, c.PrimaryKey AS TableKeyValue 
       FROM tblAccident a INNER JOIN tblAccidentNonMotorist b 
        ON a.AccidentNumber = b.AccidentNumber INNER JOIN tblAccidentNonMotoristDrug c 
         ON b.PrimaryKey = c.ForeignKey 
       AND a.AccidentNumber = '001' 
      WHERE c.DrugTestResult IN('02', '03', '04', '05', '06', '07', '08', '97', '98')  
     IF (@@ROWCOUNT > 0) 
     BEGIN 
      SET @ReturnValue = 'Y' 
     END     
    END 

    IF (@inIndicatorMode = @SpeedInd) 
    BEGIN 
     SELECT a.AccidentNumber,'AccidentUnit' AS TableFound, c.PrimaryKey AS TableKeyValue 
     FROM tblAccident a INNER JOIN tblAccidentUnit b 
      ON a.AccidentNumber = b.AccidentNumber INNER JOIN tblAccidentUnitDriverAction c 
       ON b.PrimaryKey = c.ForeignKey 
       AND a.AccidentNumber = '001' 
     WHERE c.DriverAction IN('28', '29') 
     IF (@@ROWCOUNT > 0) 
     BEGIN 
      SET @ReturnValue = 'Y' 
     END 
    END 

    Return @ReturnValue 

END 
GO 
+1

Vous pouvez utiliser la clause IN au lieu de plusieurs OR. À partir de votre troisième requête, utilisez [WHERE c.DrugTestResult IN ('02 ',' 03 ',' 04 ',' 05 ',' 06 ',' 07 ',' 08 ',' 97 ',' 98 ')] – Suirtimed

+0

Je suis assez confus par l'histoire d'édition maintenant. À un moment donné, vous avez mis en place une version avec des instructions DML et un 'begin..end 'vide qui semble avoir disparu. Pouvez-vous trier et mettre en forme le code correctement en utilisant l'icône «{}» et non les balises afin de ne pas avoir à le modifier. –

+0

@Martin - Désolé à ce sujet. Je faisais des ajustements au code et je voulais poster mon code sans toutes les instructions select pour affiner le problème que j'avais. Je suppose que je l'ai rendu plus confus. J'ai posté le code que j'ai dans les déclarations IF cette fois. – Spidermain50

Répondre

4

Il y a quelques problèmes que je vois ici.

  1. Vous avez un paramètre de type nvarchar sans une taille déclarée. Lorsque cela se produit, SQL Server par défaut à 1 caractère, ce qui n'est probablement pas ce que vous voulez. Je vous encourage à spécifier la taille.

  2. Votre fonction renvoie un nvarchar, mais vous n'avez pas déclaré la taille.

  3. Vous avez déclaré des variables locales de type nvarchar sans déclarer la taille.

  4. Vous attribuez des variables sans utiliser le mot-clé défini. SET @ReturnValue = 'Y'

EDIT

  1. Vous passez @inIndicatorMode comme un entier, mais on le compare à une variable nvarchar. Cela entraînera SQL Server à effectuer une conversion de type avant la comparaison. Les conversions de type sont généralement assez rapides, mais il est préférable de les éviter lorsque vous le pouvez.

  2. Vous semblez être des valeurs de codage absolues uniquement à des fins de comparaison. Chaque déclaration et assignation de variable prendra un peu de temps à exécuter. Le seul avantage que je vois à cette méthode est le code auto-documenté. Au lieu de déclarer des variables, d'assigner des variables, puis de comparer ces variables, je suggère que vous changiez la comparaison en une valeur codée en dur, puis que vous utilisiez des commentaires dans le code.


IF (@inIndicatorMode = 1) --Alcohol Indicator 
BEGIN 
    --select statment 
    IF (@@ROWCOUNT > 0) 
    BEGIN 
    SET @ReturnValue = 'Y' 
    END 
END 
  1. Il semble que il n'y a que deux déclarations valides de cette procédure, 'N' ou 'Y'. Je vous encourage à changer le type de données de retour à un peu. Cela vous permet d'écrire un autre code qui traite la sortie de cette fonction comme un booléen au lieu d'une chaîne.

  2. Dans votre message, vous montrez 3 blocs de code. Dans le code, vous avez un commentaire de "select statement". Je suppose que chaque instruction select est différente. Vous semblez également vérifier le @@ RowCount par la suite, et si le nombre de lignes est supérieur à 0, vous définissez la sortie de la fonction sur 'Y'. Au lieu de cela, je vous encourage à utiliser la fonction Exists à la place. Il existe un léger gain de performances lorsque vous utilisez existe car il renvoie true dès que SQL trouve une seule ligne qui satisfait la requête.Par exemple:


IF (@inIndicatorMode = 1) -- Alcohol Indicator 
BEGIN 
    If Exists(-- Your select statement Here) 
    BEGIN 
    SET @ReturnValue = 'Y' 
    END 
END 
+0

+1 Bon résumé des problèmes! –

+0

@G Mastros - Oh mec! Je n'ai pas remarqué que je passais dans un int puis en utilisant les valeurs de nvarchar pour le comparer. – Spidermain50

+0

Assurez-vous d'utiliser le dernier commentaire sur la fonction Exists. Comme votre bloc de code actuel le montre, il ne sera pas compilé car vous ne pouvez pas avoir une simple instruction select dans une fonction comme vous le faites. Je veux dire, vous pouvez créer une variable de table et sélectionner dedans, mais vous ne pouvez pas avoir une sélection directe comme vous l'avez fait. Aussi, je vous suggère de changer l'UNION à UNION ALL. Union va filtrer les doublons, ce qui ne vous intéresse pas ici. Vous recherchez simplement la présence de TOUTE ligne correspondante. –

2

Après votre édition. Vous ne pouvez pas avoir un bloc begin..end vide. Il doit contenir quelque chose même si c'est juste une déclaration d'impression ou une affectation redondante.

+0

Je pense que j'ajouterais qu'il semble que le but est de retourner un 'Y' dans tous les cas où il y a des résultats donc vous pourriez remplacer [SET @ReturnValue = 'Y'] avec [RETURN 'Y'] – Suirtimed

+1

@Suirtimed - Cela ne marcherait pas. Vous ne pouvez renvoyer des entiers avec l'instruction 'return' que des données de caractères. –

+0

merci! Je ne le savais pas. – Suirtimed

1

Il suffit de regarder votre fonction, je ne pense pas que le problème est avec le multiple si les déclarations. Il semble que le problème est que vous faites @ReturnValue = 'Y' dans chaque instruction if (oubliant SET). Il devrait être:

IF (@@ROWCOUNT > 0)  
BEGIN   
    SET @ReturnValue = 'Y'  
END 

, il semble aussi que vous faites la même chose à l'intérieur de chaque cas, vous pouvez combiner les instructions if dans un seul cas avec salles d'opération.

IF (@inIndicatorMode = @AlcoholInd OR @inIndicatorMode = @DrugInd OR @inIndicatorMode = @SpeedInd) 
BEGIN  --select statment   
    IF (@@ROWCOUNT > 0)  
    BEGIN   
    SET @ReturnValue = 'Y'  
    END 
END