Question SQL "IF", "BEGIN", "END", "END IF"?


Pas une personne SQL du tout. Avoir le code suivant écrit par un consultant.

Tout d'abord, il faut s'assurer que seule une école élémentaire a été choisie - alors, après le début, si la variable @Term est égale à 3, nous voulons faire les choses sous cette instruction IF. Voici le problème. Lorsque @Term n'est pas = 3, nous voulons toujours descendre et faire la partie SECOND INSERT INTO @Classes. FYI - le terme est = 3 quand il est en cours d'exécution, mais il ne fait pas les deux INSERT - devrait-il y avoir un IF FIN à la fin de cette section "IF @Term = 3" au lieu d'un simple END?

IF @SchoolCategoryCode = 'Elem' 

--- We now have determined we are processing an elementary school...

BEGIN

---- Only do the following if the variable @Term equals a 3 - if it does not, skip just this first part

    IF @Term = 3

    BEGIN

        INSERT INTO @Classes

        SELECT      
        XXXXXX  
        FROM XXXX blah blah blah

    END   <----(Should this be ENDIF?)

---- **always** "fall thru" to here, no matter what @Term is equal to - always do the following INSERT for all elementary schools

    INSERT INTO @Classes    
    SELECT
    XXXXXXXX    
    FROM XXXXXX (more code) 

END

32
2017-12-31 21:07


origine


Réponses:


Cela concerne la forme normale du langage SQL. Les déclarations IF peuvent, par définition, ne prendre qu'une unique Instruction SQL. Cependant, il existe un type particulier d'instruction SQL qui peut contenir plusieurs instructions SQL, le bloc BEGIN-END.

Si vous omettez le bloc début-fin, votre SQL fonctionnera correctement, mais il exécutera uniquement la première instruction dans le cadre de la FI.

Fondamentalement, ceci:

IF @Term = 3
    INSERT INTO @Classes
    SELECT              
        XXXXXX  
    FROM XXXX blah blah blah

est équivalent à la même chose avec le bloc BEGIN-END, car vous exécutez une seule instruction. Cependant, pour la même raison que ne pas inclure les accolades sur une instruction if dans une langue de type C est une mauvaise idée, il est toujours préférable d'utiliser BEGIN et END.


34
2017-12-31 21:19



Il n'y a pas d'ENDIF en SQL.

L'instruction qui suit directement une IF n'est exécutée que si l'expression if est vraie.

La construction BEGIN ... END est distincte de la IF. Il lie plusieurs instructions ensemble sous la forme d'un bloc pouvant être traité comme s'il s'agissait d'une seule déclaration. Par conséquent, BEGIN ... END peut être utilisé directement après une IF et donc tout le bloc de code de la séquence BEGIN .... END sera exécuté ou ignoré.

Dans votre cas, je soupçonne que le "(plus de code)" suivant FROM XXXXX est où votre problème est.


20
2017-12-31 21:18



Hors de main, le code a l'air correct. Et si vous essayez d'utiliser un autre et voyez ce qui se passe?

IF @SchoolCategoryCode = 'Elem' 

--- We now have determined we are processing an elementary school...

BEGIN

---- Only do the following if the variable @Term equals a 3 - if it does not, skip just this first part

    IF @Term = 3
    BEGIN
        INSERT INTO @Classes

        SELECT              
            XXXXXX  
        FROM XXXX blah blah blah

        INSERT INTO @Classes    
        SELECT
        XXXXXXXX    
        FROM XXXXXX (more code) 
    END   <----(Should this be ENDIF?)
    ELSE
    BEGIN


        INSERT INTO @Classes    
        SELECT
        XXXXXXXX    
        FROM XXXXXX (more code) 
    END
END

5
2017-12-31 21:20



S'il s'agit de MS SQL Server, ce que vous avez devrait fonctionner correctement ... En fait, techniquement, vous n'avez pas besoin de Begin & End, il n'y a qu'une seule instruction dans le bloc begin-End ... (je suppose que @Classes est une variable de table?)

If @Term = 3
   INSERT INTO @Classes
    SELECT                  XXXXXX  
     FROM XXXX blah blah blah
-- -----------------------------

 -- This next should always run, if the first code did not throw an exception... 
 INSERT INTO @Classes    
 SELECT XXXXXXXX        
 FROM XXXXXX (more code)

2
2017-12-31 21:12



Vous pouvez également réécrire le code pour supprimer complètement l'instruction 'If' imbriquée.

INSERT INTO @Classes    
SELECT XXXXXX      
FROM XXXX 
Where @Term = 3   

---- **always** "fall thru" to here, no matter what @Term is equal to - always do
---- the following INSERT for all elementary schools    
INSERT INTO @Classes        
SELECT    XXXXXXXX        
FROM XXXXXX (more code) 

2
2017-12-31 22:17



La seule fois où la deuxième insertion dans @clases échoue à se déclencher est si une erreur s'est produite dans la première instruction d'insertion.

Si tel est le cas, vous devez alors décider si la deuxième instruction doit s'exécuter avant le premier OU si vous avez besoin d'une transaction pour effectuer une restauration.


1
2017-12-31 21:23



Si je me souviens bien, et plus souvent que je ne le fais pas, il n'y a pas de support END IF dans Transact-Sql. Le début et la fin devraient faire le travail. Avez-vous des erreurs?


0
2017-12-31 21:12



Selon votre description de ce que vous voulez faire, le code semble être correct tel quel. ENDIF n'est pas un mot clé de contrôle de boucle SQL valide. Etes-vous sûr que les INSERTS extraient effectivement les données à mettre dans @Classes? En fait, si c'était mauvais, ça ne fonctionnerait pas.

Ce que vous voudrez peut-être essayer, c'est d'y mettre quelques déclarations PRINT. Placez un PRINT au-dessus de chacune des INSERTS pour ne sortir que du texte idiot pour montrer que cette ligne est en cours d'exécution. Si vous obtenez les deux sorties, alors votre SELECT ... INSERT ... est suspect. Vous pouvez aussi simplement faire le SELECT à la place du PRINT (c'est-à-dire sans INSERT) et voir exactement quelles données sont extraites.


0
2017-12-31 21:17



Franchement, cela semble être quelque chose qui devrait être sur la couche application, pas la couche de base de données ...


-9
2017-12-31 22:19