MYSQLストアドプロシージャコメントの詳細な説明

MYSQLストアドプロシージャコメントの詳細な説明

0.環境説明:

ソフトウェアバージョン
マイスク8.0
ナビキャット

1. 使用方法

ストアド プロシージャは、一連のSQLステートメントをカプセル化し、より複雑なビジネス ロジックを完了するために使用したり、パラメーターを入力および出力したりできる ( javaでのメソッドの記述に似ています)、データベース内の重要なオブジェクトです。

作成時に事前コンパイルされて保存されるため、ユーザーは後続の呼び出しで再度コンパイルする必要はありません。

// editUser をストアド プロシージャと比較する public void editUser(User user,String username){
    文字列 a = "nihao";
    user.setUsername(ユーザー名);
}
主要(){
    ユーザー user = new User();
 editUser(user,"张三");
    user.getUseranme(); //Java の基本}

「ビジネスロジックを処理するために SQL を使用する方法を学び直す必要があるが、 javaを使用してロジック (ループ判定、ループクエリなど) を処理することはできないのか?」と思われるかもしれません。では、ビジネス ロジックを処理するためにストアド プロシージャを使用するのはなぜでしょうか?

アドバンテージ:

運用環境では、サーバーを再起動せずにストアド プロシージャを直接変更することで、ビジネス ロジック (またはバグ) を変更できます。
実行速度が速い。ストアド プロシージャをコンパイルすると、1 つずつ実行するよりも高速になります。
ネットワーク送信トラフィックを削減します。
最適化に便利です。

欠点:

複雑なビジネス処理のための手続き型プログラミングと高いメンテナンスコスト。
不便なデバッグ
異なるデータベース間の移植性が低い。 -- 異なるデータベースの構文が一貫していません。

2. 準備

データベース参考資料内の SQL スクリプト:

区切り文字 $$ --宣言終了文字

3. 文法

公式参考ウェブサイト:

https://dev.mysql.com/doc/refman/5.6/en/sql-statements.html
https://dev.mysql.com/doc/refman/5.6/en/sql-compound-statements.html

#### 3.0 構文構造 ```sql
-- ストアドプロシージャ構造 CREATE
    [定義者 = ユーザー]
 プロシージャ sp_name ([proc_parameter[,...]])
    [特性...] ルーチン本体
    
-- 1. proc_parameter パラメータ部分は次のように記述できます。
 [ IN | OUT | INOUT ] パラメータ名 タイプ
 -- 型 type は MySQL でサポートされている任意の型にすることができます -- 2. ルーチン本体の部分では、有効な SQL 文 BEGIN ... END を記述できます

簡単なデモンストレーション:

-- 宣言終了文字。 MySQLはデフォルトで「;」をターミネータとして使用し、ストアドプロシージャでは「;」が文の終わりとして使用されるので、「;」と区切り文字$$が競合します。

プロシージャ hello_procedure () を作成します。
始める
 'hello プロシージャ' を選択します。
終了 $$

hello_procedure() を呼び出します。

3.1 変数と代入

javaにおけるローカル変数とメンバー変数の宣言と使用を比較する

ローカル変数:

ユーザー定義、 begin/endブロックで有効

文法:
変数をdeclare var_name type [default var_value];
例: declare nickname varchar(32);

-- 区切り文字 $$ の値を設定します
プロシージャ sp_var01() を作成する
始める
 ニックネームvarchar(32)を宣言し、デフォルトは'unkown'です。
 ニックネームを 'ZS' に設定します。
 -- ニックネームを := 'SF' に設定します。
 ニックネームを選択;
終わり$$
-- に区切り文字 $$ を割り当てます
プロシージャ sp_var_into() を作成する
始める
 emp_name varchar(32) をデフォルト 'unkown' として宣言します。
 emp_no int のデフォルトを 0 と宣言します。
 e.empno、e.ename を emp_no、emp_name から emp e に選択します (e.empno = 7839)。
 emp_no、emp_name を選択します。
終わり$$

ユーザー変数:
ユーザー定義、現在のセッション (接続) に有効です。 javaメンバー変数との類似性

文法:
@var_name
事前申告は不要、使用時に申告

-- 区切り文字を割り当てる $$
プロシージャ sp_var02() を作成する
始める
 @ニックネームを 'ZS' に設定します。
 -- ニックネームを := 'SF' に設定します。
終わり$$
sp_var02() を呼び出す $$
@nickname$$ を選択すると結果が表示されます

セッション変数:
システムによって提供され、現在のセッション(接続)に有効です

文法:

@@session.var_name

show session variables; -- セッション変数を表示します select @@session.unique_checks; -- セッション変数を表示します set @@session.unique_checks = 0; -- セッション変数を変更します

グローバル変数:
システムによって提供され、MySQLサーバー全体に有効です

文法:
@@global.var_name

例:

-- グローバル変数内の char を含む変数名の記録を表示します

'%char%' のようなグローバル変数を表示します。 

-- グローバル変数 character_set_client の値を表示します。 select @@global.character_set_client; 

3.2 入力および出力パラメータ

- 文法
in | out | inout param_name type

例:

-- IN 型デモ区切り文字 $$
プロシージャ sp_param01(age in int) を作成します。
始める
 @user_age = 年齢を設定します。
終わり$$
sp_param01(10) を呼び出す $$
@user_age$$ を選択
-- OUT タイプ、出力のみを担当します。
-- 要件: 渡されたアドレス文字列に対応する部門番号を出力します。
区切り文字 $$

プロシージャ sp_param02(in loc varchar(64),out dept_no int(11)) を作成します。
始める
 dept d から dept_no に d.deptno を選択します (d.loc = loc)。
 --ここで強調されているのは、テーブルに別名が付けられているか、パラメータ名がフィールド名と一致していないことです。
区切り文字 ;

--テスト @dept_no = 100 を設定します。
sp_param02('DALLAS',@dept_no) を呼び出します。
@dept_no を選択します。
-- INOUT型区切り文字 $$
プロシージャ sp_param03(inout name varchar(49)) を作成します。
始める
 name = concat('hello',name) を設定します。
終わり$$
区切り文字 ;

@user_name を 'Xiaoming' に設定します。
sp_param03(@user_name); を呼び出します。
@user_name を選択します。

3.3 プロセス制御-判断

公式サイトの説明
https://dev.mysql.com/doc/refman/5.6/en/flow-control-statements.html

もし

-- 構文 IF 検索条件 THEN ステートメントリスト
    [ELSEIF 検索条件 THEN ステートメント リスト] ...
    [ELSE ステートメントリスト]
終了の場合


例:

-- 前提知識: timestampdiff(unit,exp1,exp2) は差 exp2-exp1 を計算し、単位は unit です。
e.empno = '7499 ' の場合、emp e から timestampdiff(year,e.hiredate,now()) を選択します。
区切り文字 $$
-- sp_param04 が存在する場合はプロシージャを削除します。
プロシージャ sp_param05(年齢タイムスタンプ内) を作成します。
始める
 結果をvarchar(32)として宣言します。
 timestampdiff(year,ages,now())>40の場合 
  次に、 result = 'Veteran' を設定します。
 そうでない場合、timestampdiff(year,ages,now())>38 
  次に、 result = 'Old employee' を設定します。
 それ以外 
  結果 = 'Newbie' を設定します。
 終了の場合;
 結果を選択します。
終了 $$
デリミタ;
 
sp_param05('1970-02-26 10:00:25')を呼び出します。
-- 注意: MYSQL タイムスタンプは 1970 年から始まる必要があります。

場合

この構文は、ストアド プロシージャだけでなく、クエリ ステートメントでも使用できます。

-- 構文 1 (Java の switch に類似):
CASE ケース値
    WHEN when_value THEN ステートメントリスト
    [WHEN when_value THEN statement_list] ...
    [ELSE ステートメントリスト]
終了ケース
-- 構文 2:
場合
    WHEN 検索条件 THEN ステートメントリスト
    [WHEN 検索条件 THEN ステートメント リスト] ...
    [ELSE ステートメントリスト]
終了ケース


例:

-- 要件: 勤続年数 <= 新入社員の場合 38 年 > ベテラン社員の場合 38 年 <= 40 年 > ベテラン社員の場合 40 年 区切り文字 $$
プロシージャ sp_hire_case() を作成する
始める
 結果をvarchar(32)として宣言します。
 メッセージを宣言するvarchar(64);
 場合
    timestampdiff(year,'2001-01-01',now()) > 40 の場合 
  それから 
   結果を「ベテラン」に設定します。
   メッセージに「おじいちゃん」を設定します。
 timestampdiff(year,'2001-01-01',now()) > 38 の場合
  それから 
   結果を「古い従業員」に設定します。
   set message = '脂ぎった中年男';
 それ以外 
  結果を 'Newbie' に設定します。
  メッセージに「初心者」を設定します。
 終了ケース;
 結果を選択します。
終わり$$
区切り文字 ;

3.4 プロセス制御ループ

ループ

-- 構文 [begin_label:] LOOP
    ステートメントリスト
ループ終了 [end_label]

例:

loopは無限ループなので手動で終了する必要があることに注意してください。終了するには、 leave使用します。

Javaではleave breakと考えることができます。それに対応するのがiterate (継続ループ)です。これはJavaのcontinueに似ています。

--要件: ループ印刷 1 から 10
--制御ループ終了区切り文字 $$
プロシージャ sp_flow_loop() を作成する
始める
 c_index int のデフォルトを 1 と宣言します。
 result_str varchar(256) をデフォルト '1' として宣言します。
 cnt:ループ
 
  c_index >= 10の場合
  次にcntを残します。
  終了の場合;

  c_index = c_index + 1 を設定します。
  result_str を concat(result_str,',',c_index) に設定します。
  
 ループ終了 cnt;
 
 result_str を選択します。
終わり$$

-- 反復 + 制御ループ区切り文字 $$ を終了
プロシージャ sp_flow_loop02() を作成します。
始める
 c_index int のデフォルトを 1 と宣言します。
 result_str varchar(256) をデフォルト '1' として宣言します。
 cnt:ループ

  c_index = c_index + 1 を設定します。
  result_str を concat(result_str,',',c_index) に設定します。
  c_index < 10の場合 
   cnt を反復します。 
  終了の場合;
  -- 次の文は実行できますか?いつ実装されますか? c_index < 10 が false の場合、leave cnt を実行します。
  
 ループ終了 cnt;
 result_str を選択します。
 
終わり$$

繰り返す

[begin_label:] 繰り返し
    ステートメントリスト
UNTIL search_condition -- ... までループを終了します END REPEAT [end_label]
-- 要件: 1 から 10 までをループして出力します
区切り文字 $$
プロシージャ sp_flow_repeat() を作成する
始める
 c_index int のデフォルトを 1 と宣言します。
 -- 結果文字列を収集します。declare result_str varchar(256) default '1';
 count_lab:繰り返し
  c_index = c_index + 1 を設定します。
  result_str を concat(result_str,',',c_index) に設定します。
  c_index >= 10 になるまで
 count_lab の繰り返し終了;
 result_str を選択します。
終わり$$


その間

Java の while(){} との類似点
[begin_label:] WHILE 検索条件 DO
    ステートメントリスト
終了中 [end_label]
-- 要件: 1 から 10 までをループして出力します
区切り文字 $$
プロシージャ sp_flow_while() を作成する
始める
 c_index int のデフォルトを 1 と宣言します。
 -- 結果文字列を収集します。declare result_str varchar(256) default '1';
 c_index < 10 の場合
  c_index = c_index + 1 を設定します。
  result_str を concat(result_str,',',c_index) に設定します。
 終了しながら;
 result_str を選択します。
終わり$$

3.5 プロセス制御 - 終了、ループの継続

離れる

Javaのbreakeとの類似点
-- LEAVE は BEGIN ... END またはループ構造 (LOOP、REPEAT、WHILE) 内で使用できます。
LEAVEラベル

繰り返す

Javaとの類似性は続く
-- ITERATE は LOOP、REPEAT、WHILE ステートメント内でのみ使用できます。
ITERATEラベル



3.6 カーソル

カーソルを使用して結果セットを取得し、データを行ごとに処理します。

jdbc ResultSet との類似点
--宣言構文 DECLARE cursor_name CURSOR FOR select_statement
-- オープン構文 OPEN cursor_name
-- 値取得構文 FETCH cursor_name INTO var_name [, var_name] ...
-- 構文 CLOSE カーソル名を閉じる
-- 要件: 部門名で従業員を照会し、選択して従業員 ID、名前、給与を表示します。 (これはカーソルの使用方法のデモンストレーションに過ぎないことに注意してください)
-- 終了文字を $$ に変更します
区切り文字 $$
-- ストアド プロシージャを作成する (入力パラメータが 1 つ)
プロシージャ sp_create_table02(dept_name varchar(32) 内) を作成します。
始める
-- 最初に変数を宣言する必要があります。declare e_no int;
 e_name varchar(32)を宣言します。
 e_salを10進数(7,2)として宣言します。
 
 lp_flag のブール値をデフォルトで true として宣言します。
-- 次に、カーソルを宣言します。カーソルの値は、クエリ(dept_name)によって取得されたテーブル(e.empno、e.ename、e.sal)です。
 emp_cursorカーソルを宣言する 
  e.empno、e.ename、e.sal を選択
  emp e、dept dより
  ここで、e.deptno = d.deptno、d.dname = dept_name;
  
-- 次にハンドラーを宣言します。
-- ハンドルについて: https://blog.csdn.net/qq_43427482/article/details/109898934
-- これを読んでもまだ理解できない場合は、もう一度読んでください: https://www.cnblogs.com/phpper/p/7587556.html
-- SQL STATE はここで関係します: https://blog.csdn.net/u014653854/article/details/78986780
-- ハンドラを宣言します。各 SQL 文が ERROR STATE に値のないエラーを渡すと、変数 lp_flag を false に設定し、SQL 文の実行を続行します (宣言されていない場合、ループがエラーを報告すると、SQL 文全体が直接ループを停止します)
 NOT FOUND の継続ハンドラを宣言し、lp_flag を false に設定します。
-- カーソルを開きます。open emp_cursor;
-- ループを開く: emp_loop
 emp_loop:ループ
-- カーソル値を 3 つの変数に渡します。fetch emp_cursor into e_no, e_name, e_sal;
-- 変数lp_flagがtrueの場合、これら3つのパラメータの値を取得します。そうでない場合はemp_loopを中断します。
   e_no、e_name、e_sal を選択します。
  それ以外
   emp_loop を終了します。
  終了の場合;
-- ループを終了 end loop emp_loop;
-- ユーザー変数を定義し、値を割り当てます(ユーザー変数は事前に宣言する必要はなく、現在のセッションに対してのみ有効です)> この手順の意味がわかりません set @end_falg = 'exit_flag';
-- カーソルを閉じます close emp_cursor;
-- ストアドプロシージャを終了します end$$
-- 復元; 区切り文字の終了;

-- このストアド プロシージャを使用してパラメーターを渡し、sp_create_table02('RESEARCH'); を呼び出します。

特別な注意:

構文では、変数宣言、カーソル宣言、 handler宣言を順番に記述する必要があります。そうしないと、ストアド プロシージャの作成時にエラーが発生します。

3.7 ストアドプロシージャ内のハンドラ

handlerハンドルは条件付き処理を定義するために使用されます

handler_action ハンドラーを宣言する
    FOR 条件値 [, 条件値] ...
    声明

ハンドラアクション: {
    CONTINUE -- 実行を続行 | EXIT -- 実行を終了 | UNDO -- 何もしない}

CONTINUE: 現在のプログラムの実行が継続されます。 -- 現在のプログラムの実行を継続します。 EXIT: ハンドラが宣言されている BEGIN ... END 複合ステートメントの実行が終了します。これは、条件が内部ブロックで発生した場合でも当てはまります。 -- ハンドラが宣言されている BEGIN ... END 複合ステートメントの実行を停止します。これは、条件が内部ブロックで発生した場合でも当てはまります。

条件値: {
    mysql_エラーコード
  | SQLSTATE [値] sqlstate_value
  | 条件名
  | SQL警告
  | 見つかりません
  | SQL例外
}

SQLWARNING: '01' で始まる SQLSTATE 値のクラスの省略形です。 -- つまり、01 で始まるクラスです。 NOT FOUND: '02' で始まる SQLSTATE 値のクラスの省略形です。 -- つまり、02 で始まるクラスです。 SQLEXCEPTION: '00'、'01'、または '02' で始まらない SQLSTATE 値のクラスの省略形です。 -- つまり、00、01、または 02 で始まらないクラスです。 -- さまざまな書き方:
 SQLSTATE '42S01' の exit HANDLER を宣言し、@res_table を 'EXISTS' に設定します。
 1050 の continue HANDLER を宣言し、@res_table を 'EXISTS' に設定します。
 見つからない場合の続行ハンドラーを宣言し、@res_table を 'EXISTS' に設定します。

4. 練習

——ストアド プロシージャのビジネス プロセスは、通常、Java コードで実装できることに注意してください。次の要件は、ストアド プロシージャを実践するためのものです。

4.1 ストアドプロシージャを使用してデータを更新する

ある部署(指定する)の人の給与は100増加しますが、社長の場合は給与は増加しません。

delimiter // -- ターミネータを定義します。 create procedure high_sal(in dept_name varchar(32)) -- ストアド プロシージャを作成します。 begin -- ストアド プロシージャを開始します。 define e_no int; -- 変数を宣言します。 declaration e_name varchar(32);
 e_salを10進数(7,2)として宣言します。
 
 lp_flag のブール値をデフォルトで true として宣言します。
 
 emp_cursor カーソルを宣言します -- カーソルを宣言して e.empno、e.ename、e.sal を選択します
  emp e、dept dより
  ここで、e.deptno = d.deptno、d.dname = dept_name;
  
 --ハンドラハンドルを宣言する(条件付き処理)
 NOT FOUND の継続ハンドラを宣言し、lp_flag を false に設定します。
  
 open emp_cursor; -- カーソルを開く emp_loop:loop -- ループを開始する fetch emp_cursor into e_no,e_name,e_sal; -- 変数の割り当て if lp_flag then -- フロー制御 if e_name = 'king' then 
    iterate emp_loop; -- ループを続行します。 
    update emp e set e.sal = e.sal + 100 where e.empno = e_no; -- データを更新 end if;
  それ以外
   leave emp_loop; -- ループを終了します end if; -- プロセスを終了します end loop emp_loop; -- ループを終了します set @end_falg = 'exit_flag'; -- ユーザー変数を宣言します close emp_cursor; -- 変数比率カーソル end // -- ストアド プロシージャを終了します delimiter; -- ターミネータを復元します call high_sal('ACCOUNTING');

4.2 ループテーブルの作成

翌月の各日に対応するテーブルcomp_2020_04_01、comp_2020_04_02、...
を作成します。 comp_2020_04_01、comp_2020_04_02、...

(シミュレーション)要件の説明:

特定のユーザーの検索や購入行動を記録するなど、大量のデータを記録するためにテーブルを使用する必要があります (これはデータベースに保存されることが前提です)。 毎日のレコード数が多い場合、すべてのデータを 1 つのテーブルに記録するには大きすぎるため、テーブルを 2 つに分割する必要があります。 私たちの要件は、その日の統計データを格納するために毎日 1 つのテーブルを用意することであり、そのためにはこれらのテーブルを事前に作成する必要があります。つまり、毎月末に翌月の各日のテーブルを作成する必要があります。

-- 知識ポイント: 準備ステートメントを前処理した後にローカル変数を使用すると、エラーが発生します -- https://dev.mysql.com/doc/refman/5.6/en/sql-prepared-statements.html
-- 英語のドキュメントが理解できない場合は、こちらをお読みください: https://www.cnblogs.com/geaozhang/p/9891338.html; PREPARE stmt_name FROM preparable_stmt を改善するには、英語の技術ドキュメントも読む必要があります。
EXECUTE stmt_name [USING @var_name [, @var_name] ...]
{DEALLOCATE | DROP} stmt_name を準備する

-- 前処理の例: 文字列定義を使用して SQL を前処理する (直角三角形の斜辺を計算する)
PREPARE stmt1 FROM 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse'; -- POW(x,y) 関数は x の y 乗を計算するために使用されます (http://c.biancheng.net/mysql/pow_power.html); SQRT 関数は平方根を求めるために使用されます (https://blog.csdn.net/weixin_39554172/article/details/113124290)
SET @a = 3;
SET @b = 4; -- ユーザー変数の使用法は宣言です EXECUTE stmt1 USING @a, @b; -- 結果は5です
stmt1 の割り当てを解除します。 

-- ナレッジポイント: 時間処理 -- EXTRACT(unit FROM date) は、指定された位置の時刻の値を抽出します -- DATE_ADD(date,INTERVAL expr unit) 日付操作 -- LAST_DAY(date) は、日付の最終日の日付を取得します -- YEAR(date) は、日付の年を返します -- MONTH(date) は、日付の月を返します -- DAYOFMONTH(date) は、日を返します -- 注: https://stackoverflow.com/questions/35838321/day-vs-dayofmonth-in-mysql によると、実際には、DAY(date) の効果は同じです -- アイデア: ループしてテーブル名 comp_2020_05_01 から comp_2020_05_31; を構築し、create ステートメントを実行します。
-- 分析: 1. テーブルはループで構築されており、テーブル名のみが異なります。ストアド プロシージャを使用してループ処理を実行し、前処理を使用して効率を向上させることを検討してください。 2. まず、実行された SQL を格納するための変数が必要です。次に、年用の変数、月用の変数、日付用の変数、連結されたテーブル名用の変数が必要です。さらに、累積するための数値が必要です。これまでに、少なくとも 6 つの変数が必要であることがわかりました。日付 0 を完成させるために、月と日の 2 つの変数を追加して 0 を補足し、01、02 などを形成します。 3. 前処理形式(from の後にローカル変数がない)を考慮して、7 つのローカル変数と 1 つのユーザー変数区切り文字を記述します // --declaration terminator create procedure sp_create_table()
始める
-- 一連のローカル変数を定義します。declare next_year int;
 next_month int を宣言します。
 next_month_maxday int を宣言します。
  
 next_month_str char(2)を宣言します。
 next_month_maxday_str char(2)を宣言します。
 
 -- 各日のテーブル名を処理します。declare table_name_str char(10);
 -- 統計シーケンスは t_index int default 1 を宣言します。
 -- create_table_sql varchar(200) を宣言します。
 
 -- 次の月の年を取得します。set next_year = year(date_add(now(),INTERVAL 1 month));
 -- 次の月を取得します。set next_month = month(date_add(now(),INTERVAL 1 month));
 -- 翌月の最終日はいつですか? set next_month_maxday = dayofmonth(LAST_DAY(date_add(now(),INTERVAL 1 month)));
 
 -- 1月~9月は0:01,02····,09を追加
 来月 < 10 の場合
  次に、next_month_str = concat('0',next_month); を設定します。
 それ以外
  next_month_str を concat('',next_month); に設定します。
 終了の場合;
 
 
 t_index <= next_month_maxday の場合
  
  -- 上記と同様、日数に0を加算します
  (t_index < 10)の場合
   次に、next_month_maxday_str = concat('0',t_index); を設定します。
  それ以外
   next_month_maxday_str を concat('',t_index); に設定します。
  終了の場合;
  
  -- 2020_05_01
  table_name_str を concat(next_year,'_',next_month_str,'_',next_month_maxday_str) に設定します。
  -- Splice 作成 SQL ステートメント (ユーザー変数)
  @create_table_sql を連結(に設定する
     'テーブルcomp_を作成'、
     テーブル名str、
     '(`grade` INT(11) NULL,`losal` INT(11) NULL,`hisal` INT(11) NULL) COLLATE=\'utf8_general_ci\' ENGINE=InnoDB');
  -- FROM の後にはローカル変数は使用できません。そのため、ユーザー変数 prepare create_table_stmt FROM @create_table_sql; を使用します。
  create_table_stmt を実行します。
  割り当てを解除してcreate_table_stmtを準備します。
  
  t_index = t_index + 1 を設定します。
  
 終了しながら; 
終わり//
デリミタ;

sp_create_table() を呼び出す

-- 以下は区切り文字の簡略版です //
CREATE PROCEDURE sp_createtable1 () BEGIN-- DECLARE 統計シーケンス
  t_index INT デフォルト 1;
 その間
   t_index <= 日 (
    最終日(
    date_add( now(), INTERVAL 1 MONTH ))) DO
   
   SET @create_table_sql = 連結(
    'テーブルcomp_を作成',
    年 (
    date_add( now(), 間隔 1 か月 )),
    '_',
    月 (
    date_add( now(), 間隔 1 か月 )),
    '_',
    t_インデックス、
    '(`grade` INT(11) NULL、`losal` INT(11) NULL、`hisal` INT(11) NULL) COLLATE=\'utf8_general_ci\' ENGINE=InnoDB' 
   );-- FROM の後にはローカル変数は使用できません。そのため、ユーザー変数PREPARE create_table_stmtを使用します。 
  から
   テーブルを作成します。
  create_table_stmt を実行します。
  割り当てを解除して、create_table_stmt を準備します。
  
  t_index = t_index + 1 を設定します。
  
 終了しながら;
 
終わり // 
デリミタ;
sp_createtable1() を呼び出す

4.3 その他のシナリオ:

「ユーザーにショッピング ポイントを追加し、ユーザーの合計ポイント テーブルに更新する」など、複数のテーブルで CRUD 操作を必要とするビジネス。
また、トランザクション コマンドを内部的に使用することもできます。

5. その他

5.1 特徴

特徴:
    コメント '文字列'
  | 言語 SQL
  | [非]決定論的
  | { SQL を含む | SQL を含まない | SQL データを読み取る | SQL データを変更する }
  | SQL セキュリティ { 定義者 | 呼び出し者 }


SQL SECURITY の意味は次のとおりです。

MySQL ストアド プロシージャは、SQL SECURITY 句を指定して、ストアド プロシージャを実行する実際のユーザーを指定します。
SQL SECURITY 句が DEFINER として指定されている場合、ストアド プロシージャはストアド プロシージャの DEFINER を使用して実行され、ストアド プロシージャを呼び出すユーザーがストアド プロシージャのexecute権限を持っているかどうか、および DEFINER ユーザーがストアド プロシージャによって参照される関連オブジェクト (ストアド プロシージャ内のテーブルなど) に対する権限を持っているかどうかが確認されます。
SQL SECURITY 句が INVOKER として指定されている場合、MySQL は、現在ストアド プロシージャを呼び出しているユーザーとしてプロシージャを実行し、ユーザーがストアド プロシージャのexecute権限と、ストアド プロシージャによって参照される関連オブジェクトに対する権限を持っていることを確認します。
SQL SECURITY 句を明示的に指定しない場合、MySQL はデフォルトでストアド プロシージャを DEFINER として実行します。

5.2 デッドループ処理

-- 無限ループがある場合は、次のコマンドを使用して表示および終了できます: show processlist;
ID を強制終了します。

5.3 SELECT文にcaseを記述できる

制御フロー関数
選択 
 場合
  timestampdiff(year,e.hiredate,now()) <= 38 の場合、「Newbie」
  timestampdiff(year,e.hiredate,now()) <= 40 の場合、「古い従業員」
  そうでなければ「ベテラン」
 hir_loc 終了、
 e.*
emp eから;


5.4 一時テーブル

セッションが終了すると、一時テーブルは自動的に破棄されます。
一時テーブル

一時テーブルテーブル名を作成します(
  フィールド名タイプ[制約]、
  名前varchar(20) 
)Engine=InnoDB のデフォルトの文字セット utf8;

-- 要件: 部門名で従業員を照会し、選択して従業員 ID、名前、給与を表示します。 (これはカーソルの使用方法のデモンストレーションに過ぎないことに注意してください)
区切り文字 $$
プロシージャ sp_create_table02(dept_name varchar(32) 内) を作成します。
始める
 emp_no int を宣言します。
 emp_name varchar(32)を宣言します。
 emp_salを10進数(7,2)として宣言します。
 exit_flag int のデフォルトを 0 と宣言します。
 
 emp_cursorカーソルを宣言する
  e.empno、e.ename、e.sal を選択
  emp e から、e.deptno = d.deptno で dept d を内部結合します (d.dname = dept_name)。
 
 見つからない場合の継続ハンドラを宣言し、exit_flag = 1 を設定します。
 
 -- データを収集するための一時テーブルを作成します CREATE temporary TABLE `temp_table_emp` (
  `empno` INT(11) NOT NULL COMMENT '従業員番号',
  `ename` VARCHAR(32) NULL COMMENT '従業員名' COLLATE 'utf8_general_ci',
  `sal` DECIMAL(7,2) NOT NULL デフォルト '0.00' COMMENT '給与',
  BTREE を使用した主キー (`empno`)
 )
 照合='utf8_general_ci'
 エンジン=InnoDB; 
 
 emp_cursor を開きます。
 
 c_loop:ループ
  emp_cursor を emp_no、emp_name、emp_sal にフェッチします。
  
  
  exit_flag != 1 の場合
   temp_table_emp に値 (emp_no、emp_name、emp_sal) を挿入します。 
  それ以外
   c_loop を終了します。
  終了の場合;
  
 ループを終了 c_loop;
 
 temp_table_emp から * を選択します。
 
 select @sex_res; -- emp_cursor を閉じるまで実行されるかどうかを確認するだけです。
 
終わり$$

sp_create_table02('RESEARCH') を呼び出します。

付録: この例でテーブルを作成するための SQL

テーブル「dept」を作成します(
 `deptno` INT(11) NOT NULL COMMENT '部門番号',
 `dname` VARCHAR(32) NULL COMMENT '部門名' COLLATE 'utf8_general_ci',
 `loc` VARCHAR(64) NULL COMMENT '部署住所' COLLATE 'utf8_general_ci',
 BTREE を使用した主キー (`deptno`)
)
照合='utf8_general_ci'
エンジン=InnoDB
;
DEPT値に挿入
 (10、「会計」、「ニューヨーク」)
DEPT VALUES (20,'RESEARCH','DALLAS') に INSERT します。
DEPT値に挿入
 (30,'SALES','シカゴ');
DEPT値に挿入
 (40,'作戦','ボストン');
 
テーブル `emp` を作成します (
 `empno` INT(11) NOT NULL COMMENT '従業員番号',
 `ename` VARCHAR(32) NULL COMMENT '従業員名' COLLATE 'utf8_general_ci',
 `job` VARCHAR(10) NULL COMMENT 'Position' COLLATE 'utf8_general_ci',
 `mgr` INT(11) NULL COMMENT '上位番号',
 `hiredate` DATE NOT NULL COMMENT '仕事開始時間',
 `sal` DECIMAL(7,2) NOT NULL デフォルト '0.00' COMMENT '給与',
 `comm` DECIMAL(7,2) NULL COMMENT '年末ボーナス',
 `deptno` INT(11) NOT NULL COMMENT '部門番号',
 BTREEを使用した主キー(`empno`)
 インデックス `FK_emp_dept` (`deptno`) BTREE 使用、
 制約 `FK_emp_dept` 外部キー (`deptno`) 参照 `procedure_demo`.`dept` (`deptno`) ON UPDATE RESTRICT ON DELETE RESTRICT
)
照合='utf8_general_ci'
エンジン=InnoDB
;

emp値に挿入
(7369,'スミス','店員',7902,'1980-12-17',800,null,20);
emp値に挿入
(7499,'アレン','セールスマン',7698,'1981-02-20',1600,300,30);
emp値に挿入
(7521,'病棟','セールスマン',7698,'1981-02-22',1250,500,30);
emp値に挿入
(7566,'ジョーンズ','マネージャー',7839,'1981-02-04',2975,null,20);
emp値に挿入
(7654,'マーティン','セールスマン',7698,'1981-09-28',1250,1400,30);
emp値に挿入
(7698,'ブレイク','マネージャー',7839,'1981-05-01',2850,null,30);
emp値に挿入
(7782,'クラーク','マネージャー',7839,'1981-06-09',2450,null,10);
emp値に挿入
(7788,'スコット','アナリスト',7566,'1987-07-13')-85,3000,null,20);
emp値に挿入
(7839,'キング','大統領',null,'1981-11-17',5000,null,10);
emp値に挿入
(7844,'ターナー','セールスマン',7698,'1981-09-08',1500,0,30);
emp値に挿入
(7876,'アダムス','店員',7788,'1987-07-13')-51,1100,null,20);
emp値に挿入
(7900,'ジェームズ','店員',7698,'1981-12-03',950,null,30);
emp値に挿入
(7902,'フォード','アナリスト',7566,'1981-12-03',3000,null,20);
emp値に挿入
(7934,'製粉業者','店員',7782,'1982-01-23',1300,null,10);

テーブル `salgrade` を作成します (
 `グレード` INT(11) NULL,
 `losal` INT(11) NULL,
 `ヒサル` INT(11) NULL
)
照合='utf8_general_ci'
エンジン=InnoDB
;
salgrade値(1,700,1200)に挿入します。
salgrade値(2,1201,1400)に挿入します。
salgrade値(3,1401,2000)に挿入します。
salgrade値(4,2001,3000)に挿入します。
salgrade値(5,3001,9999)に挿入します。

MYSQL ストアド プロシージャ コメントの詳細な説明については、これで終わりです。MYSQL ストアド プロシージャに関するより関連性の高いコンテンツについては、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • MySQL で指定エンコーディングを実装する際の落とし穴について
  • MySQL インデックス データ構造の詳細な分析
  • MySQL データベースの必須条件クエリ ステートメント
  • MySQLデータベースのタイムアウト設定を構成する方法の例
  • Mysqlサーバーのインストール、構成、起動、シャットダウン方法の詳細な説明

<<:  メニューのホバー効果を実現するCSS3

>>:  ElementUI の el-dropdown に複数のパラメータを実装する方法

推薦する

Vue+element はローカル検索機能付きのドロップダウン メニューを実装します

必要:バックエンドは配列オブジェクトを返し、それがフロントエンドで配列に結合されます。配列は名前に従...

Docker ベースの Redis 1 マスター、2 スレーブ、3 センチネルの実装

現在、Redis とコンテナについて学習中なので、Docker を使用して Redis マスタースレ...

Vue+Vantはトップ検索バーを実装します

この記事では、参考までに、Vue+Vant のトップ検索バーを実装するための具体的なコードを紹介しま...

MySQL アーキテクチャのナレッジポイントの概要

1. データベースとデータベースインスタンスMySQL の研究では、データベースとデータベース イン...

Reactを使用する際の7つの落とし穴のまとめ

目次1. コンポーネントの肥大化2. 状態を直接変更する3. プロパティは数値を渡す必要があるが文字...

Sysbench の MySQL ベンチマーク プロセスの分析

序文1.ベンチマークは、テスト オブジェクトのクラスの特定のパフォーマンス指標の定量的、再現可能、比...

CSS マルチカラムレイアウトソリューション

1. 固定幅+適応型期待される効果: 左側は固定幅、右側は適応幅 共通コード: html: <...

JS のディープコピーとシャローコピーの詳細

目次1. 浅いコピーとはどういう意味ですか? 2. ディープコピーとはどういう意味ですか? 3. デ...

HTML コードの書き方に関する提案のまとめ

リソースファイルのプロトコルを省略する画像、メディアファイル、スタイル、スクリプトの URL では、...

MySQL 5.7 共通データ型

——「MySQL in Simple Terms (第 2 版)」からのメモ数値型整数型バイト最小最...

Windows10システムにMySQL 5.7.17をインストールする

オペレーティング システム win10 MySQL は、公式 Web サイトからダウンロードした 6...

JavaScript でフロントエンドのカウントダウン効果を実装する

この記事では、フロントエンドのカウントダウン効果を実現するためのJavaScriptの具体的なコード...

Dapr を使用してマイクロサービスをゼロから簡素化する例

目次序文1. Dockerをインストールする2. Dapr CLIをインストールする3. Net6 ...

JSはカリキュラムタイムテーブルアプレット(スーパーカリキュラムタイムテーブルを模倣)を実装し、カスタムバックグラウンド機能を追加します

概要:市販されているいくつかのタイムテーブルソフトウェアから教訓を得ました。機能が複雑すぎるため、タ...

mysql バッチで大量のデータを削除する

mysql バッチで大量のデータを削除する1000万件のレコードを持つテーブル(syslogs)があ...