Mysql - Comment quitter / quitter la procédure stockée

131

J'ai une question très simple mais je n'ai pas eu de code simple pour quitter SP en utilisant Mysql. Quelqu'un peut-il partager avec moi comment faire cela?

CREATE PROCEDURE SP_Reporting(IN tablename VARCHAR(20))
BEGIN
     IF tablename IS NULL THEN
          #Exit this stored procedure here
     END IF;

     #proceed the code
END;
Joe Ijam
la source
1
Ou, vous pouvez utiliser IF tablename IS NOT NULL THEN...;)
OMG Ponies
4
J'essaie de raccourcir fin ... sinon je dois coder à l'intérieur de l'instruction IF, et ce n'est pas la seule instruction EXIT ... que vous avez besoin d'une fonction de sortie à la place, nous faisons plusieurs IF dans Stored Proc.
Joe Ijam
Bonne URL de référence: bytes.com/topic/mysql/answers/…
Avishek

Réponses:

204
CREATE PROCEDURE SP_Reporting(IN tablename VARCHAR(20))
proc_label:BEGIN
     IF tablename IS NULL THEN
          LEAVE proc_label;
     END IF;

     #proceed the code
END;
piotrme
la source
1
Génial! Vous faites même remarquer que la END proc_label;syntaxe (indiquée dans la plupart des exemples officiels de MySQL) n'est pas nécessaire. (c'est un excellent moyen de commenter un processus stocké sans avoir à faire défiler vers le bas pour le mettre */en place)
2
pouvez-vous laisser et retourner une valeur?
ygaradon
35
Étiquetez simplement la section BEGIN de chaque proc 'this_proc'. Parce que LEAVE this_proc;ça sonne parfait!
SNag
@ygaradon Les procédures stockées ne renvoient pas de valeurs. Vous devez utiliser une fonction stockée et return <value>renvoyer une valeur.
David Harkness
1
Je pense que l'espace est nécessaire entre :et BEGINcomme proc_label:BEGINune erreur de syntaxe pendant le proc_label: BEGINtravail.
Umair Malhi
13

Si vous souhaitez une "sortie anticipée" pour une situation dans laquelle il n'y a pas eu d'erreur, utilisez la réponse acceptée publiée par @piotrm. Le plus souvent, cependant, vous serez renfloué en raison d'une condition d'erreur (en particulier dans une procédure SQL).

À partir de MySQL v5.5, vous pouvez lever une exception. Annulation des gestionnaires d'exceptions, etc. qui obtiendront le même résultat, mais d'une manière plus propre et plus poignante.

Voici comment:

DECLARE CUSTOM_EXCEPTION CONDITION FOR SQLSTATE '45000';

IF <Some Error Condition> THEN      
    SIGNAL CUSTOM_EXCEPTION
    SET MESSAGE_TEXT = 'Your Custom Error Message';
END IF;     

Remarque SQLSTATE '45000'équivaut à une "condition d'exception définie par l'utilisateur non gérée". Par défaut, cela produira un code d'erreur de 1644(qui a la même signification). Notez que vous pouvez lancer d'autres codes de condition ou codes d'erreur si vous le souhaitez (ainsi que des détails supplémentaires pour la gestion des exceptions).

Pour en savoir plus sur ce sujet, consultez:

https://dev.mysql.com/doc/refman/5.5/en/signal.html

Comment signaler une erreur dans une fonction MySQL

http://www.databasejournal.com/features/mysql/mysql-error-handling-using-the-signal-and-resignal-statements.html

Addenda

En relisant mon article, j'ai réalisé que j'avais quelque chose de plus à ajouter. Avant MySQL v5.5, il y avait un moyen d'émuler la levée d'une exception. Ce n'est pas exactement la même chose, mais c'était l'analogue: créer une erreur en appelant une procédure qui n'existe pas. Appelez la procédure par un nom qui est significatif afin d'obtenir un moyen utile de déterminer quel était le problème. Lorsque l'erreur se produit, vous verrez la ligne d'échec (en fonction de votre contexte d'exécution).

Par exemple:

CALL AttemptedToInsertSomethingInvalid;

Notez que lorsque vous créez une procédure, aucune validation n'est effectuée sur de telles choses. Ainsi, alors que dans quelque chose comme un langage compilé, vous ne pourriez jamais appeler une fonction qui n'était pas là, dans un script comme celui-ci, elle échouera simplement à l'exécution, ce qui est exactement ce que l'on souhaite dans ce cas!

BuvinJ
la source
1
Cela me semble être la réponse la plus correcte et la plus complète et c'était exactement ce que je voulais. Comme l'OP, j'ai plusieurs tests (validation d'entrée) que je dois exécuter et je ne voulais pas tous les imbriquer, donc cela fonctionne bien pour moi.
Fodagus
12

Pour gérer cette situation de manière portable (c'est-à-dire qu'elle fonctionnera sur toutes les bases de données car elle n'utilise pas l'étiquette MySQL Kung fu), divisez la procédure en parties logiques, comme ceci:

CREATE PROCEDURE SP_Reporting(IN tablename VARCHAR(20))
BEGIN
     IF tablename IS NOT NULL THEN
         CALL SP_Reporting_2(tablename);
     END IF;
END;

CREATE PROCEDURE SP_Reporting_2(IN tablename VARCHAR(20))
BEGIN
     #proceed with code
END;
Bohème
la source
7
Yucks, pourquoi ne pas utiliser la première solution à la place?
Pacerier
1
J'aimerais pouvoir voter deux fois. Le simple fait que SQL ne soit pas un vrai langage de programmation ne donne à personne une excuse pour écrire plus de 200 lignes de code en une seule procédure.
Max Heiber
Cette réponse est-elle tout simplement fausse ou est-ce que je manque quelque chose? Pourquoi a-t-il des votes positifs? Il existe manifestement un moyen d'y parvenir qui est démontré par la solution acceptée.
jlh
@jlh il était faux (texte corrigé maintenant) dans ce que je ne connaissais pas la technique de l' étiquette de MySQL, mais le code est mauvais - il fonctionnera, sur une base de données réellement.
Bohème
2

Pourquoi pas ça:

CREATE PROCEDURE SP_Reporting(IN tablename VARCHAR(20))
BEGIN
     IF tablename IS NOT NULL THEN
          #proceed the code
     END IF;
     # Do nothing otherwise
END;
Stephen
la source
7
Le code est très long ... je ne peux pas l'utiliser ... C'est juste un exemple.
Joe Ijam
Quelle que soit la longueur, il ne s'exécutera pas.
Stephen
Si vous vous inquiétez de l'indentation, supprimez simplement la section entière de l' ifinstruction. C'est logiquement identique à un «retour anticipé».
bobobobo
@bobobobo, Il dit que dans son cas, il est logiquement beaucoup plus logique de ne pas recâbler la logique autour de cette limitation SQL.
Pacerier
1
Peut-être qu'il a un login avec beaucoup de vérifications "si x EST NULL ALORS SETresult = -1". Vous voulez qu'il arrête VRAIMENT de faire des choses. Cela réduit la complexité des ifs. Moins {} annidé
borjab
2

Cela fonctionne pour moi:

 CREATE DEFINER=`root`@`%` PROCEDURE `save_package_as_template`( IN package_id int , 
IN bus_fun_temp_id int  , OUT o_message VARCHAR (50) ,
            OUT o_number INT )
 BEGIN

DECLARE  v_pkg_name  varchar(50) ;

DECLARE  v_pkg_temp_id  int(10)  ; 

DECLARE  v_workflow_count INT(10);

-- checking if workflow created for package
select count(*)  INTO v_workflow_count from workflow w where w.package_id = 
package_id ;

this_proc:BEGIN   -- this_proc block start here 

 IF  v_workflow_count = 0 THEN
   select 'no work flow ' as 'workflow_status' ;
    SET o_message ='Work flow is not created for this package.';
    SET  o_number = -2 ;
      LEAVE this_proc;
 END IF;

select 'work flow  created ' as 'workflow_status' ;
-- To  send some message
SET o_message ='SUCCESSFUL';
SET  o_number = 1 ;

  END ;-- this_proc block end here 

END
Devendra Singraul
la source
0
MainLabel:BEGIN

IF (<condition>) IS NOT NULL THEN
    LEAVE MainLabel;
END IF; 

....code

i.e.
IF (@skipMe) IS NOT NULL THEN /* @skipMe returns Null if never set or set to NULL */
     LEAVE MainLabel;
END IF;
sdfor
la source