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 構成チュートリアルとプラグイン

推薦する

Vue3 の動的コンポーネントはどのように機能しますか?

目次1. コンポーネントの登録1.1 グローバル登録1.2 グローバルコンポーネントの登録プロセス1...

Vue は PDF ファイルのオンライン プレビューを実装します (pdf.js/iframe/embed を使用)

序文現在、私はコースウェア PPT のオンライン プレビューを必要とする高品質のコースに取り組んでい...

システムメンテナンスページにリダイレクトするように nginx を設定する

先週末、兄弟プロジェクトはより良いサービスを提供するためにサーバーを拡張する準備をしていました。兄弟...

Vueを使用して天気コンポーネントをロードする方法の詳細な説明

この記事では、Vueを使用して天気コンポーネントをロードする方法を参考までに紹介します。具体的な内容...

mysql5.7.21 utf8 エンコーディングの問題と Mac 環境での解決方法

1. 目標: mysql の character_set_server の値を latin1 から ...

MySQL 5.7.21 解凍バージョンのインストールと設定のグラフィックチュートリアル

この記事では、MySQL 5.7.21の解凍版をダウンロードしてインストールする詳細な手順を記録して...

Dockerコンテナシェルスクリプトの実行ステータスを監視する方法

シナリオ会社のプロジェクトはDockerでデプロイされています。原因不明ですが、コンテナが時々停止し...

Kylin V10 サーバーで Storm をコンパイルしてインストールする詳細なプロセス

1 はじめにApache Storm は、Hadoop と同様に、大量のデータを処理するために使用で...

JavaScript で二分探索木を実装する

JavaScriptでの検索二分木実装は参考までに。具体的な内容は以下のとおりです。バイナリ検索木 ...

HTML独習の旅(I)基本要素と属性の練習(自分でコードを書く)

私は W3school のチュートリアルに従いました。チュートリアルはとても良いと思います。各セクシ...

MySQLデータのエクスポートとインポートに関する知識ポイントの簡単な分析

多くの場合、ローカル データベースのデータをエクスポートしたり、他のデータベースからデータをインポー...

Vue 円形パーセンテージ プログレスバー コンポーネントの機能の実装

必要な方はどなたでも参考にしてください。試してみて問題が見つかった場合は、メッセージを残してお知らせ...

Flash での HTML と CSS の適用

Flash での HTML と CSS の適用:同僚の Den が Flash で HTML と C...

Windows 10 での MySQL 8.0.22 のインストールと設定方法のグラフィック チュートリアル

MySQL 8.0.22のインストールと設定方法のグラフィックチュートリアル、参考までに、具体的な内...

Vue ElementUI フォームのフォーム検証

フォーム検証は、フロントエンド開発プロセスで最もよく使用される機能の 1 つです。私の個人的な仕事経...