Mysql - Depolanan yordamdan nasıl çıkılır / çıkılır


131

Çok basit bir sorum var ama Mysql kullanarak SP'den çıkmak için herhangi bir basit kod alamadım. Bunun nasıl yapılacağını benimle paylaşan var mı?

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
Veya şunu kullanabilirsiniz IF tablename IS NOT NULL THEN...;)
OMG Ponies

4
Kısayolu düzeltmeye çalışıyorum ... aksi takdirde IF ifadesinin içinde kodlamam gerekiyor ve bu tek EXIT ifadesi değil ... yi çıkış işlevine ihtiyaç duyuyor, bunun yerine Stored Proc içinde birden fazla IF yapıyoruz.
Joe Ijam

Yanıtlar:


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
Harika! Hatta END proc_label;sözdiziminin (çoğu resmi MySQL örneğinde gösterilen) gerekli olmadığını söylüyorsunuz. (bu, yerleştirmek için en alta kaydırmak zorunda kalmadan depolanan bir işlemi yorumlamanın harika bir yoludur */)

2
bırakıp bir değer verebilir misin?
ygaradon

35
Her işlemin BEGIN bölümünü 'this_proc' olarak etiketlemeniz yeterlidir. Çünkü LEAVE this_proc;kulağa mükemmel geliyor!
2014

@ygaradon Saklanan yordamlar değer döndürmez. Depolanmış bir işlevi kullanmanız ve return <value>bir değer döndürmeniz gerekir.
David Harkness

1
Ben arasındaki boşluk gerekli olduğunu düşünüyorum :ve BEGINşekilde proc_label:BEGINolan yazım hatası verdi proc_label: BEGINçalıştı.
Umair Malhi

13

Hata olmayan bir durum için "erken çıkış" istiyorsanız, @piotrm tarafından gönderilen kabul edilmiş yanıtı kullanın. Bununla birlikte, en tipik olarak, bir hata durumu nedeniyle (özellikle bir SQL prosedüründe) kefalet ödeyeceksiniz.

MySQL v5.5'ten itibaren bir istisna atabilirsiniz. Aynı sonucu daha temiz ve daha dokunaklı bir şekilde elde edecek istisna işleyicileri vb.

Bunu nasıl yapacağınız aşağıda açıklanmıştır:

DECLARE CUSTOM_EXCEPTION CONDITION FOR SQLSTATE '45000';

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

Not SQLSTATE '45000', "İşlenmemiş kullanıcı tanımlı istisna koşulu" na eşittir. Varsayılan olarak, bu bir hata kodu üretecektir 1644(aynı anlama sahiptir). İsterseniz başka koşul kodlarını veya hata kodlarını (artı istisna işleme için ek ayrıntılar) atabileceğinizi unutmayın.

Bu konu hakkında daha fazla bilgi için şunlara göz atın:

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

MySQL işlevi içinde bir hata nasıl oluşturulur

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

ek

Bu yazımı yeniden okurken ekleyeceğim ek şeyler olduğunu fark ettim. MySQL v5.5'ten önce, bir istisna atmayı taklit etmenin bir yolu vardı. Tam olarak aynı şey değil, ama bu analogdu: Varolmayan bir prosedürü çağırarak bir hata yaratın. Sorunun ne olduğunu belirlemek için faydalı bir yol elde etmek için prosedürü anlamlı bir adla çağırın. Hata oluştuğunda, hata satırını göreceksiniz (yürütme içeriğinize bağlı olarak).

Örneğin:

CALL AttemptedToInsertSomethingInvalid;

Bir prosedür oluşturduğunuzda, bu tür şeyler üzerinde herhangi bir doğrulama yapılmadığını unutmayın. Dolayısıyla, derlenmiş bir dil gibi bir şeyde, orada olmayan bir işlevi asla çağıramazsınız, böyle bir komut dosyasında, çalışma zamanında basitçe başarısız olur, bu durumda tam olarak istenen şey budur!


1
Bu bana en doğru ve eksiksiz yanıt gibi geliyor ve tam da istediğim şey buydu. OP gibi, çalıştırmam gereken birkaç testim var (giriş doğrulama) ve hepsini iç içe geçirmek istemedim, bu yüzden bu benim için iyi çalışıyor.
Fodagus

12

Bu durumu taşınabilir bir şekilde ele almak için (yani, MySQL etiketi Kung fu kullanmadığı için tüm veritabanlarında çalışacaktır), prosedürü aşağıdaki gibi mantıksal bölümlere ayırın:

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
Yucks, bunun yerine neden ilk çözümü kullanmıyorsun?
Pacerier

1
Keşke bunu iki kez oylayabilseydim. Sırf SQL gerçek bir programlama dili olmadığı için hiç kimseye tek bir prosedürde 200'den fazla satır kod yazmak için bir bahane vermez.
Max Heiber

Bu cevap tamamen yanlış mı yoksa bir şeyi mi kaçırıyorum? Neden olumlu oylar var? Açıkça kabul edilen çözümün gösterdiği, bunu başarmanın bir yolu var.
jlh

@jlh o oldu ben mysql etiketi tekniği hakkında bilmediğim (metin şimdi düzeltilmiş) yanlış, ama kodu yanlış değil - aslında herhangi DB üzerinde çalışacaktır.
Bohemian

2

Neden bu değil:

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
Kod çok uzun ... bunu kullanamam ... Bu sadece bir örnek.
Joe Ijam

Uzunluk ne olursa olsun çalışmayacaktır.
Stephen

Girintileme konusunda endişeleniyorsanız, ifadedeki tüm bölümün girintisini kaldırın if. Mantıksal olarak "erken dönüş" ile aynıdır.
bobobobo

@bobobobo, kendi durumunda, mantıksal olarak bu sql sınırlaması etrafındaki mantığı yeniden düzenlememenin çok daha mantıklı olduğunu söylüyor.
Pacerier

1
"Eğer x NULL OLDUĞUNDA, SETresult = -1 ise" birçok kontrol içeren bir girişi olabilir. Bir şeyler yapmayı GERÇEKTEN durdurmasını istiyorsunuz. Ifs karmaşıklığını azaltır. Daha az {} açıklandı
borjab

2

Bu benim için çalışıyor:

 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;
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.