Mysql - Come uscire / uscire dalla procedura memorizzata


131

Ho una domanda molto semplice ma non ho ricevuto alcun codice semplice per uscire da SP usando Mysql. Qualcuno può condividere con me come farlo?

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;

1
Oppure, potresti usare IF tablename IS NOT NULL THEN...;)
OMG Ponies

4
Sto provando a scorciatoia ... altrimenti devo codificare all'interno dell'istruzione IF, e questa non è l'unica istruzione EXIT ... che ho bisogno della funzione di uscita invece facciamo IF multipli all'interno di Stored Proc.
Joe Ijam,

Buon URL di riferimento: bytes.com/topic/mysql/answers/…
Avishek

Risposte:


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;

1
Grande! Fai notare che la END proc_label;sintassi (mostrata nella maggior parte degli esempi MySQL ufficiali) non è necessaria. (questo è un ottimo modo per commentare un proc memorizzato senza dover scorrere fino in fondo per metterlo */in atto)

2
puoi lasciare e restituire un valore?
Ygaradon,

35
Basta etichettare la sezione INIZIO di ogni proc 'this_proc'. Perché LEAVE this_proc;sembra perfetto!
SNag

@ygaradon Le stored procedure non restituiscono valori. È necessario utilizzare una funzione memorizzata e return <value>restituire un valore.
David Harkness,

1
Penso che sia necessario spazio tra :e BEGINcome proc_label:BEGINerrore di sintassi dato mentre ha proc_label: BEGINfunzionato.
Umair Malhi,

13

Se si desidera una "uscita anticipata" per una situazione in cui non si sono verificati errori, utilizzare la risposta accettata inviata da @piotrm. Più in genere, tuttavia, verrà eseguito il bailing a causa di una condizione di errore (soprattutto in una procedura SQL).

A partire da MySQL v5.5 è possibile generare un'eccezione. Negare i gestori di eccezioni, ecc. Che otterranno lo stesso risultato, ma in modo più pulito e toccante.

Ecco come:

DECLARE CUSTOM_EXCEPTION CONDITION FOR SQLSTATE '45000';

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

Nota SQLSTATE '45000'equivale a "Condizione di eccezione definita dall'utente non gestita". Per impostazione predefinita, questo produrrà un codice di errore di 1644(che ha lo stesso significato). Nota che puoi lanciare altri codici di condizione o codici di errore se lo desideri (oltre a ulteriori dettagli per la gestione delle eccezioni).

Per ulteriori informazioni su questo argomento, controlla:

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

Come generare un errore all'interno di una funzione MySQL

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

appendice

Mentre rileggo questo mio post, mi sono reso conto di avere qualcosa in più da aggiungere. Prima di MySQL v5.5, c'era un modo per emulare il lancio di un'eccezione. Non è esattamente la stessa cosa, ma questo era l'analogo: creare un errore chiamando una procedura che non esiste. Chiamare la procedura con un nome che sia significativo al fine di ottenere un mezzo utile per determinare quale fosse il problema. Quando si verifica l'errore, vedrai la linea di errore (a seconda del contesto di esecuzione).

Per esempio:

CALL AttemptedToInsertSomethingInvalid;

Si noti che quando si crea una procedura, non esiste alcuna convalida eseguita su tali elementi. Quindi, mentre in qualcosa come un linguaggio compilato, non potresti mai chiamare una funzione che non c'era, in uno script come questo fallirà semplicemente in fase di esecuzione, che è esattamente ciò che si desidera in questo caso!


1
Questa è la risposta più corretta e completa per me ed era esattamente quello che volevo. Come l'OP, ho diversi test (convalida dell'input) che devo eseguire e non volevo nidificarli tutti, quindi questo funziona bene per me.
Fodagus,

12

Per gestire questa situazione in modo portatile (cioè funzionerà su tutti i database perché non utilizza l'etichetta MySQL Kung fu), suddividere la procedura in parti logiche, in questo modo:

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;

7
Che schifo, perché non usare invece la prima soluzione?
Pacerier

1
Vorrei poterlo votare due volte. Solo perché SQL non è un vero linguaggio di programmazione non offre a nessuno una scusa per scrivere oltre 200 righe di codice in un'unica procedura.
Max Heiber,

Questa risposta è semplicemente sbagliata o mi sto perdendo qualcosa? Perché ha voti positivi? Chiaramente c'è un modo per raggiungere questo obiettivo che è dimostrato dalla soluzione accettata.
jlh

@jlh era sbagliato (testo corretto ora) in quanto non sapevo della tecnica dell'etichetta di mysql, ma il codice non è sbagliato - funzionerà su qualsiasi DB in realtà.
Boemo

2

Perché non questo:

CREATE PROCEDURE SP_Reporting(IN tablename VARCHAR(20))
BEGIN
     IF tablename IS NOT NULL THEN
          #proceed the code
     END IF;
     # Do nothing otherwise
END;

7
Il codice è molto lungo ... non posso usare questo ... Questo è solo un esempio.
Joe Ijam,

Indipendentemente dalla lunghezza, non verrà eseguito.
Stephen,

Se sei preoccupato per il rientro, basta dissociare l'intera sezione dell'istruzione if. È logicamente identico a un "ritorno anticipato".
bobobobo,

@bobobobo, Sta dicendo che nel suo caso ha logicamente molto più senso non ricablare la logica attorno a questa limitazione sql.
Pacerier

1
Può essere che abbia un login con molti controlli "se x IS NULL THEN SETresult = -1". Vuoi che smetta davvero di fare le cose. Riduce la complessità degli if. Meno {} annidato
borjab il

2

Questo funziona per me:

 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

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;
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.