Mysql-ストアドプロシージャを終了/終了する方法


131

非常に単純な質問がありますが、Mysqlを使用してSPを終了するための単純なコードがありませんでした。誰でも私とそれを行う方法を共有できますか?

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...;)
OMGポニー

4
私はショートカットを細かくしようとしています...そうでない場合は、IFステートメント内でコーディングする必要があります。これは唯一のEXITステートメントではありません...その代わりに、ストアドプロシージャ内で複数のIFを実行するために終了関数が必要です。
Joe Ijam

回答:


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
離れて値を返すことができますか?
ygaradon 2014

35
すべてのプロシージャの「BEGIN」セクションに「this_proc」というラベルを付けるだけです。そのためLEAVE this_proc;音は完璧!
SNag 2014年

@ygaradonストアドプロシージャは値を返しません。あなたは、保存された使用する必要がある機能をしてreturn <value>値を返します。
David Harkness 2014

1
私は、間にスペースが必要だと思う:BEGINproc_label:BEGINしながら、構文エラーを与えたproc_label: BEGIN働きました。
Umair Malhi 2017

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
これは私にとって最も正確で完全な答えのように感じられ、まさに私が欲しかったものでした。OPと同様に、いくつかのテスト(入力検証)を実行する必要があり、それらすべてを入れ子にしたくなかったので、これは私にとってはうまく機能します。
Fodagus

12

この状況を移植可能な方法で処理するには(つまり、MySQLラベルKung fuを使用しないため、すべてのデータベースで機能します)、次のように手順を論理部分に分割します。

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
ああ、最初のソリューションを代わりに使用してみませんか?
Pacerier、2015

1
これを2票投票できるといいのですが。SQLが実際のプログラミング言語ではないからといって、単一の手順で200行以上のコードを書く口実は誰にもありません。
Max Heiber 2015

この答えはまったく間違っていますか、それとも何か不足していますか?なぜ賛成票があるのですか?明らかに、これを実現する方法があり、これは受け入れられたソリューションによって実証されています。
jlh 2018年

@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
コードが非常に長い...これは使用できません...これは単なるサンプルです。
Joe Ijam

長さに関係なく、実行されません。
スティーブン

インデントが心配な場合は、ifステートメントのセクション全体のインデントを解除してください。論理的には「アーリーリターン」と同じです。
bobobobo 2013

@bobobobo、彼は彼の場合、このsqlの制限の周りのロジックを再配線しないほうが論理的にずっと理にかなっていると言っています。
Pacerier、2015

1
「xがNULLの場合、SETresult = -1の場合」という多数のチェックを含むログインがある可能性があります。あなたは本当にそれをやめたいと思っています。ifsの複雑さを軽減します。少なくなった{}記念
ボルジャブ

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;
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.