MySQL ストアド プロシージャのエラー処理例の詳細な説明

MySQL ストアド プロシージャのエラー処理例の詳細な説明

この記事では、例を使用して MySQL ストアド プロシージャのエラー処理について説明します。ご参考までに、詳細は以下の通りです。

ストアド プロシージャでエラーが発生した場合は、現在のコード ブロックの実行を続行または終了し、意味のあるエラー メッセージを発行するなど、適切に処理することが重要です。 MySQL では、警告や例外などの一般的な条件から、特定のエラー コードなどの特定の条件に至るまで、さまざまな条件を処理するハンドラーを簡単に定義できます。ここで、DECLARE HANDLER ステートメントを使用してハンドラーを宣言してみましょう。まず構文を見てみましょう。

condition_value ステートメントのアクション HANDLER を宣言します。

上記の SQL では、条件の値が condition_value と一致する場合、MySQL は statement を実行し、操作に基づいて現在のコード ブロックを続行または終了します。アクションは次のいずれかの値を受け入れます。

  • CONTINUE: 囲んでいるコード ブロック (BEGIN ... END) の実行を継続します。
  • EXIT: ハンドラは囲まれたコード ブロックの実行の終了を宣言します。

condition_value は、ハンドラーをアクティブにする特定の条件または条件のクラスを指定します。 condition_value は次のいずれかの値を受け入れます。

  • MySQL エラー コード。
  • 標準の SQLSTATE 値、または SQLWARNING、NOTFOUND、または SQLEXCEPTION 条件 (SQLSTATE 値のクラスの省略形) になります。 NOTFOUND 条件は、カーソルまたは SELECT INTO variable_list ステートメントで使用されます。
  • MySQL エラー コードまたは SQLSTATE 値に関連付けられた名前付き条件。

最も重要なのは、上記の SQL は、単純なステートメントでも、BEGIN キーワードと END キーワードで囲まれた複合ステートメントでもかまわないということです。さて、これで準備は整いましたので、ハンドラーの宣言の例をいくつか見てみましょう。まず、プログラムでエラーが発生すると、has_error 変数の値が 1 に設定され、実行が続行されます。

SQLEXCEPTION の CONTINUE ハンドラーを宣言し、has_error = 1 を設定します。

次に、エラーが発生したときに、前の操作をロールバックし、エラー メッセージを発行して、現在のコード ブロックを終了する方法を見てみましょう。 ストアド プロシージャの BEGIN END ブロック内で宣言すると、ストアド プロシージャは直ちに終了します。

SQLEXCEPTION の終了ハンドラを宣言する
始める
ロールバック;
SELECT 'エラーが発生しました。操作はロールバックされ、ストアド プロシージャは終了しました';
終わり;

次のハンドラは、カーソルまたは select into ステートメントの場合に、フェッチする行がなくなったときに、no_row_found 変数の値を 1 に設定して実行を続行することを意味します。

NOT FOUND SET no_row_found = 1 の継続ハンドラーを宣言します。

次のハンドラーは、重複キー エラーが発生した場合に MySQL エラー 1062 を発行します。 エラー メッセージを発行して実行を続行します。

1062 の継続ハンドラを宣言する
SELECT 'エラー、重複キーが発生しました';

上記の例は少し抽象的かもしれないので、article_tags という新しいテーブルを作成し、次の操作を実行してみましょう。

testdbを使用します。
テーブル article_tags を作成します(
  記事ID INT、
  タグID INT、
  主キー(記事ID、タグID)
);

このうち、article_tags テーブルには記事とタグの関係が格納されます。各記事には複数のタグが付いている場合があり、その逆も同様です。 簡単にするために、article テーブルと tags テーブルを作成しません。また、article_tags テーブルに外部キーも作成しません。

最後に、記事 ID とタグ ID を article_tags テーブルに挿入するストアド プロシージャを作成しましょう。

testdbを使用します。
区切り文字 $$
CREATE PROCEDURE insert_article_tags(IN article_id INT, IN tag_id INT)
始める
 1062 の継続ハンドラを宣言する
 SELECT CONCAT('重複キー (',article_id,',',tag_id,') が見つかりました') AS msg;
 -- article_tags に新しいレコードを挿入します
 article_tags(article_id,tag_id) に挿入します
 VALUES(記事ID、タグID);
 -- 記事のタグ数を返す
 article_tagsからCOUNT(*)を選択します。
終わり$$
区切り文字 ;

次に、以下に示すように、 insert_article_tags ストアド プロシージャを呼び出して、記事 ID 1 にタグ ID 1、2、3 を追加します。

insert_article_tags(1,1)を呼び出します。
insert_article_tags(1,2)を呼び出します。
insert_article_tags(1,3)を呼び出します。

重複キーを挿入して、ハンドラーが実際に呼び出されるかどうかを確認してみましょう。

insert_article_tags(1,3)を呼び出します。

上記のクエリステートメントを実行すると、次の結果が得られます。

mysql> insert_article_tags(1,3) を呼び出します。
+----------------------------+
| メッセージ |
+----------------------------+
| 重複キー (1,3) が見つかりました |
+----------------------------+
セット内の1行
+----------+
| カウント(*) |
+----------+
| 3 |
+----------+
セット内の1行
クエリは正常です。影響を受けた行は 0 行です

実行後、エラーメッセージが表示されます。 ただし、ハンドラーを CONTINUE ハンドラーとして宣言したため、ストアド プロシージャは実行を継続します。したがって、記事の最終的なタグカウント値は 3 になります。写真を見てみましょう:

ただし、ハンドラー宣言内の CONTINUE を EXIT に変更すると、エラー メッセージが表示されるだけです。次のクエリ ステートメント:

区切り文字 $$
プロシージャ insert_article_tags_exit(IN article_id INT, IN tag_id INT) を作成します。
始める
 SQLEXCEPTION の終了ハンドラを宣言する 
 SELECT 'SQLException が呼び出されました';
 1062 の終了ハンドラを宣言する 
    SELECT 'MySQL エラー コード 1062 が呼び出されました';
 SQLSTATE '23000' の終了ハンドラを宣言します
 SELECT 'SQLSTATE 23000 が呼び出されました';
 -- article_tags に新しいレコードを挿入します
 article_tags(article_id,tag_id) に挿入します
  VALUES(記事ID、タグID);
 -- 記事のタグ数を返す
 article_tagsからCOUNT(*)を選択します。
終了 $$
区切り文字 ;

上記のクエリステートメントを実行すると、次の結果が得られます。

mysql> insert_article_tags_exit(1,3) を呼び出します。
+---------------------------------+
| MySQL エラー コード 1062 が発生しました |
+---------------------------------+
| MySQL エラー コード 1062 が発生しました |
+---------------------------------+
セット内の1行
クエリは正常です。影響を受けた行は 0 行です

写真を見てみましょう:

エラーを処理するために複数のハンドラを使用する場合、MySQL はエラーを処理するために最も具体的なハンドラを呼び出します。これには優先順位の問題が関係しているので、詳しく見てみましょう。

エラーは常に MySQL エラー コードにマッピングされます。これは MySQL で最も具体的なコードであるためです。 SQLSTATE は多くの MySQL エラー コードにマップできるため、それほど具体的ではありません。 SQLEXCPETION または SQLWARNING は SQLSTATES タイプの値の略語であるため、最も一般的です。次のように、 insert_article_tags_3 ストアド プロシージャで 3 つのハンドラーが宣言されているとします。

区切り文字 $$
プロシージャ insert_article_tags_3(IN article_id INT, IN tag_id INT) を作成します。
始める
 DECLARE EXIT HANDLER FOR 1062 SELECT '重複キー エラーが発生しました';
 SQLEXCEPTION SELECT 'SQLException が発生しました' の終了ハンドラーを宣言します。
 SQLSTATE '23000' の終了ハンドラーを宣言します。 'SQLSTATE 23000' を選択します。
 -- article_tags に新しいレコードを挿入します
 article_tags(article_id,tag_id) に挿入します
 VALUES(記事ID、タグID);
 -- 記事のタグ数を返す
 article_tagsからCOUNT(*)を選択します。
終了 $$
区切り文字 ;

次に、ストアド プロシージャを呼び出して、重複キーを article_tags テーブルに挿入します。

insert_article_tags_3(1,3) を呼び出します。

以下に示すように、MySQL エラー コード ハンドラーが呼び出されていることがわかります。

mysql> insert_article_tags_3(1,3) を呼び出します。
+----------------------------------+
| 重複キーエラーが発生しました |
+----------------------------------+
| 重複キーエラーが発生しました |
+----------------------------------+
セット内の1行
クエリは正常です。影響を受けた行は 0 行です

これで終了です。次は、名前付きエラー条件の使用について見てみましょう。次のように、エラー ハンドラーの宣言から始めます。

1051 SELECT の EXIT HANDLER を宣言します 'まずテーブル abc を作成してください';
abcから*を選択します。

数字1051は何を意味するのでしょうか? このように多くの数値を使用する大規模なストアド プロシージャ コードがあると想像してください。コードの保守は悪夢になります。幸いなことに、MySQL には、条件に関連付けられた名前付きエラー条件を宣言するための DECLARE CONDITION ステートメントが用意されています。 DECLARE CONDITION ステートメントの構文は次のとおりです。

条件名条件を条件値として宣言します。

condition_value は、1015 などの MySQL エラー コード、または SQLSTATE 値になります。 condition_value は condition_name によって表されます。宣言後は、condition_value の代わりに condition_name を参照できます。したがって、上記のコードは次のように書き直すことができます。

1051 に対して table_not_found 条件を宣言します。
DECLARE EXIT HANDLER FOR table_not_found SELECT 'まずテーブル abc を作成してください';
abcから*を選択します。

このコードは明らかに前のコードよりも読みやすくなっていますが、条件宣言はハンドラーまたはカーソル宣言の前に記述する必要があることに注意する必要があります。

さて、今回はここまでです。

MySQL 関連のコンテンツに興味のある読者は、このサイトの次のトピックをチェックしてください: 「MySQL ストアド プロシージャ スキル」、「MySQL 共通関数の概要」、「MySQL ログ操作スキル」、「MySQL トランザクション操作スキルの概要」、および「MySQL データベース ロック関連スキルの概要」

この記事が皆様のMySQLデータベース設計に役立つことを願っています。

以下もご興味があるかもしれません:
  • MySQL の if 文と case 文の概要
  • MySQLストアドプロシージャにおけるカーソル(DECLARE)の原理と使い方の詳細な説明
  • 複数の値を返す MySQL ストアド プロシージャ メソッドの例
  • MySQL ストアド プロシージャを作成 (CREATE PROCEDURE) して呼び出す (CALL) 方法と、変数を作成 (DECLARE) して割り当てる (SET) 方法
  • ストアド プロシージャでエラー状態をトリガーする mysql ストアド プロシージャの分析例 (SIGNAL および RESIGNAL ステートメント)
  • MySQL ストアド プロシージャの原理と使用法の詳細な説明
  • MySQL ストアド プロシージャでの変数の定義と割り当て
  • MySQL ストアド プロシージャ カーソル ループの使用の概要
  • MySQL ストアド プロシージャの例 (トランザクション、出力パラメータ、ネストされた呼び出しを含む)
  • MySql ストアド プロシージャと関数の詳細な説明
  • MySQL ストアド プロシージャで if ステートメントを使用する詳細な例

<<:  Vueはシンプルな虫眼鏡効果を実装します

>>:  VSCode 開発 UNI-APP 構成チュートリアルとプラグイン

推薦する

MySQL 最適化チュートリアル: 大規模なページングクエリ

目次背景制限の最適化最適化方法1. カバーインデックスを使用する2. サブクエリの最適化3. 遅延連...

複数の無関係なテーブルからデータをクエリし、MySQL でページングする方法

MySQL 複数の無関係なテーブルクエリデータとページング機能要件主キーと外部キーの関連付けがない ...

ウェブサイトデザインの経験 ウェブサイト構築におけるよくある間違いのまとめ

注意: 計画、設計、開発のいずれの場合でも、これらの間違いは避けなければなりません。 1. ナビゲー...

CSSを使用してHTMLテキストボックス内のテキストの垂直方向の中央を制御する

Text の height 属性が定義されている場合、Text に入力されたテキストは垂直方向に中央...

MySQL に大量のデータを挿入するときに重複データを除外する方法

目次1. 問題を発見する2.重複したデータを残さずにすべて削除する3. 削除テーブルから重複データを...

JavaScript の条件付きアクセス属性と矢印関数の紹介

目次1. 条件付きアクセス属性2. アロー関数の紹介1. 条件付きアクセス属性?. は ES2020...

シンプルなドラッグ効果を実現するJavaScript

この記事では、簡単なドラッグ効果を実現するためのJavaScriptの具体的なコードを参考までに紹介...

Vueはスクロールロードテーブルを実装します

目次成果を達成する転がり荷重知識備蓄コンポーネントのパッケージ1. コンポーネントの命名2. 小道具...

Vue 監視プロパティと計算プロパティ

目次1. 監視プロパティを監視する1. ショッピングカート2. すべて選択し、すべて選択解除する2....

JS を使用して要素が配列であるかどうかを判断する例

検証できるデータの種類は次のとおりです a = [1,2,3,4,5,6]とします。 b = [とし...

MySQL 8.0.18 インストール構成の最適化チュートリアル

MySQLのインストール、設定、最適化は参考用です。具体的な内容は次のとおりです。 MySQL ダウ...

JavaScript クラス配列の詳細な理解

js 配列はどこでも使用されているため、おそらく誰もがよく知っているでしょうが、配列クラス (疑似配...

Dockerのオンラインおよびオフラインインストールと一般的なコマンド操作

1. テスト環境名前バージョンセント7.6ドッカー18.09.06 2. オンラインインストールここ...

Linux で実行中のバックグラウンド プログラムを表示および終了する方法

Linux タスク管理 - バックグラウンド実行と終了fg、bg、ジョブ、&、ctrl + ...

Nginx + consul + upsync を使用して動的負荷分散を実現する方法の詳細な説明

目次前提条件DNSドメイン名解決プロセス外部ネットワークマッピングnginxコア知識nginxとはア...