मैसकल - संग्रहीत कार्यविधि से कैसे बाहर निकलें / बाहर निकलें


131

मेरे पास बहुत ही सरल सवाल है, लेकिन मुझे एसक्यूएल से बाहर निकलने के लिए कोई सरल कोड नहीं मिला है। क्या कोई मेरे साथ साझा कर सकता है?

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
या, आप उपयोग कर सकते हैं IF tablename IS NOT NULL THEN...;)
ओएमजी पोनीज

4
मैं शॉर्ट कट को ठीक करने की कोशिश कर रहा हूं ... नहीं तो मुझे IF स्टेटमेंट के अंदर कोड करना होगा, और यह केवल EXIT स्टेटमेंट नहीं है ... कि yi को एक्जिट फंक्शन की जरूरत है, बजाय इसके कि हम कई IF को Stored Proc के अंदर करें।
जो इज्म

अच्छा संदर्भ यूआरएल: bytes.com/topic/mysql/answers/...
Avishek

जवाबों:


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
महान! आप यहां तक ​​बताते हैं कि END proc_label;सिंटैक्स (अधिकांश आधिकारिक MySQL उदाहरणों में दिखाया गया है) की आवश्यकता नहीं है। (यह एक शानदार तरीका है जिसे स्टोर किए गए */

2
क्या आप मूल्य छोड़ सकते हैं और वापस कर सकते हैं?
यज्ञदोन

35
बस हर proc के BEGIN सेक्शन को 'this_proc' लेबल करें। क्योंकि LEAVE this_proc;सही लगता है!
19

@ygaradon संग्रहीत कार्यविधियाँ मान नहीं लौटाती हैं। आपको एक संग्रहीत फ़ंक्शन का उपयोग करने और return <value>एक मूल्य वापस करने की आवश्यकता है ।
डेविड हार्कस

1
मुझे लगता है कि अंतरिक्ष के लिए आवश्यक है के बीच :और BEGINके रूप में proc_label:BEGINसिंटेक्स त्रुटि दे दी है, जबकि proc_label: BEGINकाम किया।
उमैर माली

13

यदि आप ऐसी स्थिति के लिए "प्रारंभिक निकास" चाहते हैं जिसमें कोई त्रुटि नहीं थी, तो @piotrm द्वारा पोस्ट किए गए स्वीकृत उत्तर का उपयोग करें। आम तौर पर, हालांकि, आप एक त्रुटि स्थिति (विशेष रूप से एक SQL प्रक्रिया) के कारण परेशान हो रहे होंगे।

MySQL v5.5 के रूप में आप एक अपवाद फेंक सकते हैं। अपवाद हैंडलर आदि की उपेक्षा करना, जो एक ही परिणाम प्राप्त करेगा, लेकिन एक क्लीनर में, अधिक मार्मिक तरीके से।

ऐसे:

DECLARE CUSTOM_EXCEPTION CONDITION FOR SQLSTATE '45000';

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

नोट SQLSTATE '45000'"अनहैंडल्ड यूज़र-डिफ़ाइंड अपवाद स्थिति" के बराबर है। डिफ़ॉल्ट रूप से, यह एक त्रुटि कोड का उत्पादन करेगा 1644(जिसका वही अर्थ है)। ध्यान दें कि यदि आप चाहें तो अन्य शर्त कोड या त्रुटि कोड फेंक सकते हैं (अपवाद हैंडलिंग के लिए अतिरिक्त विवरण)।

इस विषय पर अधिक जानकारी के लिए देखें:

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

MySQL फ़ंक्शन के भीतर एक त्रुटि कैसे बढ़ाएं

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

परिशिष्ट

जैसा कि मैं इस पोस्ट को फिर से पढ़ रहा हूं, मुझे एहसास हुआ कि मेरे पास जोड़ने के लिए कुछ अतिरिक्त है। MySQL v5.5 से पहले, एक अपवाद फेंकने का अनुकरण करने का एक तरीका था। यह वास्तव में एक ही बात नहीं है, लेकिन यह एनालॉग था: एक प्रक्रिया को कॉल करके एक त्रुटि बनाएं जो मौजूद नहीं है। एक नाम से प्रक्रिया को कॉल करें जो एक उपयोगी साधन प्राप्त करने के लिए सार्थक है जिससे यह निर्धारित किया जा सके कि समस्या क्या थी। जब त्रुटि होती है, तो आपको विफलता की रेखा (आपके निष्पादन के संदर्भ के आधार पर) देखने को मिलेगी।

उदाहरण के लिए:

CALL AttemptedToInsertSomethingInvalid;

ध्यान दें कि जब आप एक प्रक्रिया बनाते हैं, तो ऐसी चीजों पर कोई सत्यापन नहीं किया जाता है। इसलिए एक संकलित भाषा की तरह कुछ में, आप कभी भी एक फ़ंक्शन को कॉल नहीं कर सकते हैं, जो इस तरह से स्क्रिप्ट में नहीं था, यह बस रनटाइम पर विफल हो जाएगा, जो इस मामले में वांछित है!


1
यह मुझे सबसे सही, पूरी तरह से जवाब की तरह लगता है और वास्तव में मैं यही चाहता था। ओपी की तरह, मेरे पास कई परीक्षण (इनपुट सत्यापन) हैं जिन्हें मुझे चलाने की आवश्यकता है और मैं उन सभी को घोंसला नहीं बनाना चाहता हूं, इसलिए यह मेरे लिए अच्छी तरह से काम करता है।
फोडागस

12

इस स्थिति को पोर्टेबल तरीके से संभालने के लिए (अर्थात सभी डेटाबेस पर काम करेगा क्योंकि यह MySQL लेबल कुंग फू का उपयोग नहीं करता है), इस तरह से तर्क भागों में प्रक्रिया को तोड़ें:

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
यक्स, इसके बजाय पहले समाधान का उपयोग क्यों नहीं करते?
पचेरियर

1
काश मैं इसे दो बार वोट कर सकता। सिर्फ इसलिए कि एसक्यूएल एक वास्तविक प्रोग्रामिंग भाषा नहीं है, यह किसी को भी एक प्रक्रिया में 200+ कोड की लाइनें लिखने का बहाना नहीं देता है।
मैक्स हाइबर

क्या यह जवाब सिर्फ सादा गलत है या मैं कुछ याद कर रहा हूं? इसका उत्थान क्यों होता है? स्पष्ट रूप से इसे प्राप्त करने का एक तरीका है जिसे स्वीकृत समाधान द्वारा प्रदर्शित किया जाता है।
jlh

@jlh यह गलत था (अब सही किया गया पाठ) इसमें मुझे mysql के लेबल तकनीक के बारे में नहीं पता था, लेकिन कोड गलत नहीं है - यह वास्तव में किसी भी DB पर काम करेगा।
बोहेमियन

2

ऐसा क्यों नहीं:

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
कोड बहुत लंबा है ... मैं इसका उपयोग नहीं कर सकता ... यह सिर्फ एक नमूना है।
जो इज्म

कोई फर्क नहीं पड़ता लंबाई, यह निष्पादित नहीं करेगा।
स्टीफन

यदि आप इंडेंटिंग के बारे में चिंतित हैं, तो बस स्टेटमेंट में पूरे सेक्शन को एक करें if। यह तार्किक रूप से "शुरुआती रिटर्न" के समान है।
बोब्बोबो

@bobobobo, वह अपने मामले में कह रहा है कि यह तार्किक रूप से बहुत अधिक समझ में नहीं आता है क्योंकि इस sql सीमा के आसपास तर्क को फिर से नहीं जाना है।
पचेरियर

1
हो सकता है कि उसके पास बहुत सारे चेक के साथ लॉगिन हो "अगर x IS NULL THEN SETresult = -1" है। आप इसे वास्तव में बातें करना बंद करना चाहते हैं। यह इफ्स की जटिलता को कम करता है। कम {} सत्यानाश किया
बोरोबज़

2

यह मेरे लिए काम करता है:

 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;
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.