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

推薦する

Linux C ログ出力コード テンプレート サンプル コード

序文この記事は主に Linux C でのログ出力コード テンプレートに関する関連コンテンツを紹介し、...

Reactでプロキシを有効にする2つの実用的な方法

プロキシを有効にする2つの方法React には、直接使用できるカプセル化された Ajax リクエスト...

JS を使用してクリップボード内の Excel コンテンツを解析する方法

目次序文1. イベントとクリップボードを貼り付ける2. クリップボード内のコンテンツ形式3. HTM...

React の 10 個のフックの紹介

目次ReactHook とは何ですか? Reactは現在フックを提供している1. 使用状態2.use...

Vue3 テーブルコンポーネントの使用

目次1. Antデザインビュー1. 公式ウェブサイトアドレス2. 使い方3.電子書籍テーブルを表示す...

Linux ユーザー状態とカーネル状態間の通信方法の詳細な説明

CPU 権限の制限により、Linux ユーザー状態とカーネル状態間の通信は、プロセス間通信を使用した...

js SMS認証コード入力ボックスを手動で実装する

序文この記事では、私が手動で実装したフロントエンドの一般的な SMS 認証コード入力コンポーネントと...

Node.js は、異なるリクエストパスに応じて異なるデータを返します。

目次1. 異なるリクエストパスに応じて異なるデータを返す方法を学びます。 2. 送信データ: データ...

MySQL 単一テーブルクエリの例の詳細な説明

1. データを準備するこのテーブルでは次の操作が実行されます 学生テーブルを作成 ( id int ...

Linuxカーネルで中国語の文字を出力する方法

次のように、Windows/MacOS からログインした Linux の SSH ターミナルで簡単に...

Centos7 構成 fastdfs および nginx 分散ファイル ストレージ システムの実装プロセス分析

1. libfastcommon-1.0.43 をインストールします。インストール パッケージは h...

MySQL は低速クエリを可能にします (EXPLAIN SQL ステートメントの使用の概要)

今日、データベース操作はますますアプリケーション全体のパフォーマンスのボトルネックになりつつあり、こ...

さまざまなターミナルで Mac が SSH 経由でリモート サーバーに接続する方法の説明

Macはシェル(ターミナル)SSHを使用してリモートサーバーに接続します前提条件: 接続する必要があ...

Reactフックの仕組み

目次1. React フックと純粋関数2. シンプルなmyUseState 3. myUseStat...

VSCode の Remote-SSH を使用して Linux に接続し、リモート開発を行う

Remote-SSHをインストールして設定するまず VSCode を開き、拡張機能を見つけて、Rem...