Procédures cataloguées en FULL SQL

BoTTom |    Changer de couleur
 
 Il est possible de créer des procédures cataloguées SQL en SQL PSM
 
    (même langage que les bases Oracle avec PL/SQL)
 
 ATTENTION :
 
    cela va créer un programme OS/400 qui sera référencé dans les
         catalogues SQL (SYSPROCS et SYSPARMS dans QSYS2)
 
    mais pour créer ce programme OS, SQL va générer un source C contenant
         du SQL et appeler le compilateur.
 
 
    il faut donc le compilateur C sur votre machine jusqu'à la V4R50.
 
 
 
 (la version 4.4 de l'OS va amener les fonctions, qui pourrons elles
   aussi être écrites en SQL ==> mêmes contraintes, jusqu'en V4r50)
 
 


|    Changer de couleur
 
Exemple général :
 
  CREATE PROCEDURE xxxxxxx/P1
         (in  nouveau_module CHAR(10) ,
          out probleme       integer  )
         LANGUAGE SQL
 
         BEGIN ATOMIC
              DECLARE UNDO HANDLER FOR SQLEXCEPTION
                          SET probleme = -1;
 
              FOR v1 as C1 cursor for SELECT module, nomcours
                                       FROM COURS
                  DO
                  IF nomcours <> ' '
                     THEN
                     UPDATE COURS SET module = nouveau_module
                     WHERE CURRENT OF C1 ;
                  END IF ;
              END FOR;
         END


|    Changer de couleur
 
 I/ syntaxe générale 
 
          --ATOMIC------
 BEGIN ---              ------------------>
          --NOT ATOMIC--
 
     déclaratives
       .../...
 
 
     instructions SQL
       .../...
       .../...
 
 END
 
 ATOMIC ==>   l'ensemble de la procédure doit être réalisé comme un tout,
               vous ne pouvez pas placer d'ordres COMMIT/ROLLBACK
 
 NOT ATOMIC   pas de validation/invalidation automatique, vous définissez
               vos transactions par COMMIT/ROLLBACK.


|    Changer de couleur
 
 II/ déclaratives :
 
 on peut déclarer des variables (sauf les paramètres qui sont déja déclarés)
 
                                          ---DEFAULT NULL-----
    DECLARE ---nom-variable----type-sql---                    -----
                                          ---DEFAULT val/dft--
 
 
 
 on peut assigner des noms aux codes erreurs SQL :
 
    DECLARE ---nom-condition--- CONDITION FOR -----code-erreur
 
 
     code-erreur:       '01234'       = code 1234
                        SQLEXCEPTION  = erreur <0
                        SQLWARNING    = erreur >0 (sauf 100)
                        NOT FOUND     = erreur 100
 
 


|    Changer de couleur
 
 déclaration de condition d'erreur (sorte de MONMSG ..)
 
   on déclare 1/ l'erreur (code ou nom-condition)
 
              2/ le traitement
 
              3/ la reprise après traitement.
                                                             (1)
 
    DECLARE   ------------------------  HANDLER FOR  code-erreur--------->
                !              !
             (3)!--CONTINUE----!
                !              !
                !--EXIT--------!
                !              !
                !--UNDO--------!
 
 
   >-------instruction SQL ;
                 (2)
 


|    Changer de couleur
 
  la reprise :
 
     dans tous les cas on exécute le traitement (2) avant de gérer
      la reprise (3)
 
 
 
     CONTINUE =  on continue le code en séquence.
                 (si l'erreur a lieu dans un IF, CASE, WHILE, on sort
                  et on se débranche à l'instruction qui suit le IF ...)
 
 
     EXIT     =  on va au END
 
 
     UNDO     =  on annule tous les changements (ROLLBACK) puis EXIT,
 
                  ce qui implique  BEGIN ATOMIC !
 
 
 


|    Changer de couleur
 
 III/ Instructions :
 
  toutes les instructions SQL sont valides, aussi bien les ordres de gestion
   de la base (CREATE, GRANT, ...) que les ordres de manipulation.
 
 plus, en assignation :
 
  SET nom-variable = expression (même possibilités que SELECT)
 
 et en structuration  :
 
  IF  --test----THEN--instruction;---------->
 
  >----------------------------------------->
    !                                 !
    !-ELSEIF test2 THEN instruction2;-!
 
  >--------------------------END IF ;------->
    !                    !
    !-ELSE instruction3;-!
 


|    Changer de couleur
 
CASE
 
1ere forme
 
  CASE--nom-variable----------------------->
 
  >---WHEN valeur1 THEN instruction1;------>
 
   >----------------------------------------->
     !                                !
     !-WHEN valeur2 THEN instruction2;!
 
    >------------------------END CASE;
     !                    !
     !-ELSE instruction3;-!
 
 
 
  chaque test se fait par égalité et sur la même variable.
 
 


|    Changer de couleur
 
CASE
 
2eme forme
 
  CASE------------------------------------->
 
  >---WHEN test1---THEN instruction1;------>
 
   >----------------------------------------->
     !                              !
     !-WHEN test2 THEN instruction2;!
 
    >------------------------END CASE;
     !                    !
     !-ELSE instruction3;-!
 
 chaque test peut utiliser :
 
             - un autre opérateur que l'égalité.
             - une variable différente.
 


|    Changer de couleur
 
LOOP (boucle)
 
    -----------------LOOP---------->
     !-label:--!
 
     série d'instructions SQL;----->
 
    ----END LOOP;
 
le seul moyen de sortir de la boucle est LEAVE
 
WHILE (boucle conditionnée, tant que)
 
    -----------------WHILE--condition pour boucler--- DO ---->
     !-label:--!
 
     série d'instructions SQL;----->
 
    ----END WHILE;
 
 la condition est testée AVANT de faire.


|    Changer de couleur
 
 
REPEAT (boucle conditionnée, jusqu'à)
 
    -----------------REPEAT ---->
     !-label:--!
 
     série d'instructions SQL;----->
 
    --UNTIL (condition d'arret)
 
    ----END REPEAT;
 
 la condition est testée en fin de boucle (après).
 
 
  LEAVE
 
  ----LEAVE label-------->
 
      sortie de la boucle qui s'appelle "label"
 


|    Changer de couleur
 
FOR  (exécution d'une série d'instructions pour chaque ligne d'un curseur)
 
     -------------FOR nomf -------------------------------------->
      !-label:--!           !                                 !
                            !--AS nomcurseur CURSOR FOR-------!
 
    ----------clause SELECT------------- DO -------------->
 
     série d'instructions SQL;----->
 
    END FOR;
 
si vous utilisez un nom de curseur il doit être unique
   (non déclaré par DECLARE CURSOR)
sinon, il sera déclaré implicitement.
 
toutes les variables retournées par le SELECT doivent être unique (jointure)
si vous utilisez AS [nocli AS codeclient] c'est "codeclient" que vous devez
    manipuler dans la boucle.
 
et enfin "nomf" n'est pas utilisable dans la série d'instructions.


|    Changer de couleur
 
  l'ordre FOR remplace la série suivante :
 
 ..............................................................
 :   DECLARE ... pour chaque variable du SELECT               :
 :                                                            :
 :   DECLARE C1 CURSOR FOR (votre SELECT)                     :
 :                                                            :
 :   OPEN C1;                                                 :
 :                                                            :
 :   FETCH C1 INTO (les variables déclarées plus haut);       :
 :                                                            :
 :   WHILE (fin de fichier non rencontrée)                    :
 :                                                            :
 :     ---vos instructions SQL;---                            :
 :                                                            :
 :     FETCH C1 INTO (les variables déclarées plus haut);     :
 :                                                            :
 :   END WHILE;                                               :
 :                                                            :
 :   CLOSE C1 ;                                               :
 :............................................................:


|    Changer de couleur
 
 Quelques exemples :
 
 
 FOR :
 
 BEGIN
 DECLARE nomlong  CHAR(40);
          FOR vl AS
              c1 CURSOR FOR
            SELECT prenom , init , nom  FROM personp1
             DO
               SET nomlong  =
                  nom  concat ', ' concat prenom concat
                       ' (' concat init concat ')';
               INSERT INTO TNOMS VALUE ( nomlong );
          END FOR;
 END
 
 
 
 


|    Changer de couleur
 
  avec des curseurs :
 
  ins_loop:
            LOOP
               CALL RETURN_serviveINFO (SERVICE, SERVNOM, SERVADM);
               IF SERVICE IS NULL THEN
                 LEAVE ins_loop;
               ELSE
                 INSERT INTO DEPARTMENT (SERVICE , SERVNOM, SERVADM) ;
            END LOOP;
 
  fetch_loop:
            LOOP
               FETCH c1 INTO
                   v_prenom, v_init,
                   v_nom
               IF SQLCODE <> 0 THEN
                  LEAVE fetch_loop;
            END LOOP fetch_loop;
            CLOSE c1;
 


|    Changer de couleur
 
 BEGIN
 DECLARE n_salaire  DECIMAL(9,2);
 DECLARE v_nopers CHAR(6) DEFAULT '123456';
 
             SELECT salaire
                  INTO n_salaire
                  FROM personp1
                  WHERE nopers = v_nopers;
               IF code  = 1
                THEN SET n_salaire =
                             n_salaire + (n_salaire * 0,10);
                ELSEIF code  = 2
                THEN SET n_salaire =
                             n_salaire + (n_salaire * 0,05);
               END IF;
 
               UPDATE personp1
                  SET salaire = n_salaire
                  WHERE nopers = v_nopers;
 END
 


|    Changer de couleur
 
Et enfin, :
 
CREATE PROCEDURE PROC1 () LANGUAGE SQL
 BEGIN
 DECLARE v_prenom VARCHAR(12);
 DECLARE v_init CHAR(1);
 DECLARE v_nom VARCHAR(15);
 DECLARE v_coef SMALLINT;
 DECLARE v_salaire DECIMAL(9,2);
 DECLARE wEOF INT DEFAULT 0;
 
  DECLARE not_found
                   CONDITION FOR '02000';
  DECLARE c1 CURSOR FOR
              SELECT prenom, init, nom,
                                coef, salaire
              FROM personp1;
  DECLARE CONTINUE HANDLER FOR not_found
                        SET wEOF = 1;
 
 


|    Changer de couleur
 
 
            OPEN c1;
 
            FETCH c1 INTO v_prenom, v_init,
                        v_nom, v_coef, v_salaire;
             WHILE wEOF = 0 DO
 
 
                (traitement de la ligne lue)
 
 
                FETCH c1 INTO
                             v_prenom, v_init,
                             v_nom, v_coef, v_salaire;
             END WHILE;
 
            CLOSE c1;
 
 
 END
 





©AF400