MySQL ストアドプロシージャで処理を途中で抜け出す方法って知ってる?
私が知らなかっただけかもしれせんが、処理を途中で抜けることってストアドプロシージャって出来ないとばかり思っていたのですが、できるんですね汗
今まで、ストアドでこんなIF文のネスティングで書いてました。可読性悪いし、バグを誘発するしで何か良い手はないのかな?って思ってました
今までのダメな書き方
CREATE PROCEDURE `sp_test_proc`( IN _mode tinyint, -- (0: Normal 1: force delete 2: Batch ) INOUT _value varchar(32) , OUT _result_code int(11) ) BEGIN BEGIN IF _mode = 1 OR _mode = 2 OR _mode = 3 THEN IF _value='test' THEN SET _value = CONCAT(_value, '-TEST') ; ELSE SET _result_code = 8888 ; END IF ; ELSE SET _result_code = 9999 ; END IF ; 〜以降略 END ; END $$
あ。。処理何やっているの?とか、コードの書き方が変とかの指摘はなしで。。なんて、IF のネスティングを延々と書いてました。理由は前述の通り、処理を途中で抜ける方法を知らなかったからです。。
よくよく考えたら、おかしいなって調べていたら当たり前のように、そういうやり方がありました。いやあ、はじめて、BEGIN - END の意味を知った感じでお恥ずかしいです。。
LEAVE 構文を活用しよう!!
LEAVE 構文って知ってました?俺知らなかったです(汗 この構文、
このステートメントは、特定のラベルを持つフロー制御構造構文を終了するために使用されます。そのラベルがもっとも外側のストアドプログラムブロックのものである場合、LEAVE はプログラムを終了します。
。。とのことで、普通にあるんじゃんって、じゃー上記のダメな書き方をLEAVE使ったらどんだけ洗練されるの?って話ですが、こんな感じになります
これからの(自分の中で)いけているストアドプロシージャの書き方
CREATE PROCEDURE `sp_test_proc`( IN _mode tinyint, -- (0: Normal 1: force delete 2: Batch ) INOUT _value varchar(32) , OUT _result_code int(11) ) root:BEGIN main:BEGIN IF _mode NOT IN (1,2,3) THEN SET _result_code = 9999 ; LEAVE main ; END IF ; IF _value != 'test' THEN SET _result_code = 8888 ; LEAVE main ; END IF ; SET _value = CONCAT(_value, '-TEST') ; 〜以降略 END ; END $$
いかがでしょうか?ちょっと制御文の書き方まで変更してしまったので若干うさんくさくなってきましたが。 LEAVE文を使うことにより、指定したラベルから処理を途中で抜け出すことが可能になります。
ここでいうラベルとは、BEGINの前に書かれた main:BEGINのことを行っております。 LEAVE main ;構文は、mainと書かれてるBEGIN - ENDどか途中離脱する動きをするんですね。 便利!なんだけど、昔よく論争になった、GO TO文論争みたいになりますが、便利なものは便利!!自分的には、IF文ネスティングよりまし!!って思いつつ、この話を終わりたいと思います。
ちょっと話はそれますが、ストアドプロシージャは是非ともデータベースエンジニアの方は、覚えておいて損はないと思います。プログラムを開発する人の手助けになりますし、データ周りの複雑なビジネスロジックは、プログラムのコードで書くよりストアドプロシージャで内包して、プログラムからCALLかけてもらったほうが、プログラムソース側も洗練されますし、SQL周りの管理もデータベースエンジニアの方は一元管理できますので、チューニングしやすいですよ。(ただし、更新系に限る)