MySQLのストアド・プロシージャ、ファンクションおよびトリガー

ストアドプロシージャと関数に対する態度I.

利点:
各実行用にコンパイルする必要がコンパイルされ、SQL文を作成するときにのみ1.ストアドプロシージャを。実行のデータベースの速度を向上させることができます。
パッケージと連動して動作が複雑2.シンプルなもの。
3.高い再利用性。
4.安全、権利にストアドプロシージャを指定するために使用することができます。

では実際のプロジェクトのストアドプロシージャや関数の使用最小限に抑える必要があり、次のような理由のために:

1. 貧しい移植は、MySQLでのストアドプロシージャは必ずしも使用されないsqlseverにグラフト。

2. トラブルのデバッグ、エラーデシベル年央報告書ではなく概念レポートアプリケーション層でのミスを、それが直接のエラーに壊滅的な打撃になります:1045は、より多くのものを、この無知。

3. 拡張性は高くありません

そのため、大規模なプロジェクトのインターネット時代に(使用しない)ストアドプロシージャと関数を使用を最小限に抑える必要があります。

II。ストアドプロシージャを作成します。

2.1ストアドプロシージャとは何ですか?

ストアドプロシージャと格納された機能が設定されたSQL文のセットです。これらのステートメントのセットは、全体としてデータベースに格納されています。

2.2構文は、ストアドプロシージャを作成します。

プロシージャを作成するストアドプロシージャ名(パラメータリスト)

                    SQL文

例:

//区切り
)(手続きのプロを作成するには
、SQLデータの読み取り
を開始
STU SELECT * FROM。
終わり

だから我々は今、ストアドプロシージャのプロを持っているが、彼は、ストアドプロシージャのパラメータは、彼がちょうどクエリ操作を行うことではありません。

我々は今、このストアドプロシージャの構造を説明します。

彼が話すとき、私たちは最後の行が実行を停止しますまで、//するためにそれを変換する必要が停止し、とき、彼はセミコロンに会ったSQLの実行ので、区切り文字//はセミコロンに変換されます。

SQLデータの解釈は、読み取り専用モードだけでなく、他のモード状態の特徴である読み込み:SQL文なしなしSQL、INSのSQL文が含まれていないの読み取りと書き込み、SQLデータはデータ等の文を書くと、変更します。

複数の文のコレクションは、我々が開始および終了しなければならないときに、ストアドプロシージャ/ *** /終了時間を開始

//全体のストアドプロシージャの終わり

2.3ストアドプロシージャを使用

ただ、その後どのように我々はそれがこのストアドプロシージャを使用しない、ストアドプロシージャを作成するには?

構文:(ストアドプロシージャ名をコール)

プロ使用上のストアドプロシージャの例:

プロを呼び出し();

 

2.4パラメータを持つストアドプロシージャを作成します。

パラメータのリスト:パラメータは、ストアドプロシージャへの3種類があり:IN、OUT、INOUTパラメータも受信および送信パラメータ、すなわち受信および送信パラメータを表します。

例:まず、我々は2つのテーブルを作成します。カリキュラムは、テーブルからの学生のテーブルです

create table stu(
stu_id bigint primary key auto_increment,#学号
stu_name varchar(10) not null,#姓名
stu_major int not null,#专业号
stu_sex char,#性别
stu_in date,#入学日期
stu_birth date,#出生日期
foreign key (stu_major) references major(ma_id)#专业外键设置
);

create table major(
ma_id int primary key,
ma_name varchar(15)、
Ma_boss VARCHAR10 
); 
INSERT  INTO主要な1 、 "情報管理"、 "ジョー・スミス");
 INSERT  INTOメジャー2 、 "eコマース"、 "ジョン・ドウ");
 INSERT  INTO STUの1。 "ボブ"、1、 "M"、 " 2017 - 09 - 01 " " 1998年- 12である- 23れる");
 INSERT  INTO STUの2 ""高い小、1、 "男"、 " 2017 - 09 - 01 "、 " 1998年- 05 - 01 ")。
挿入  STUの3、 "小李"、2、 "男"、 " 2017 - 09 - 01 "、 " 1999年- 04 - 01 ")。

 

のは、学生の専攻の名前を見つけるために、パラメータを持つストアドプロシージャを作成してみましょう、次のようにコードは次のとおりです。

デリミタ// 
作成 手順(PRO1  SNAMEのVARCHAR10)、アウトMAのVARCHAR10 ))
SQLデータの読み取り
開始
選択 ma_nameの MA から主要ここ ma_idは=選択 stu_major から STU ここ stu_name = SNAME)を、
終了
//

このストアドプロシージャを使用して次のようにコードです。

SETの @ma = "の前にノー問い合わせ"; 
Pro1の( "李"、コール@ma );
 SELECT  @ma

結果は以下の通りであります:

解释一下代码:首先使用set @ma 定义一个全局变量,然后在使用call 存储过程名 语法调用存储过程,同时全局变量ma的值也改变了。

三.创建一个存储函数

3.1存储过程和存储函数的不同。

1.在函数中必须要有return返回值

2.在存储过程中参数有in  out   inout三种,默认为in类型,但是在函数中只有一种in类型。

3.2创建一个函数

语法:create  function 函数名()

         return 返回类型

          sql语句集合

例子:

delimiter //
create function fun1(num int)
returns int
begin
return num+1000;
end
//

显然函数与存储过程的最大的区别就是在于return

3.3调用函数

使用语法不在使用关键字call,而是关键字select ,select  函数名

例子:

select fun1(100);

结果:

 

四.删除存储函数和存储过程

 语法:drop   procedure  |   function  存储过程名或者是函数名

 例子:

drop procedure pro;

 注意他是不带括号的

 

五.在存储过程和存储函数中使用游标

5.1为什么需要游标?

ストアドプロシージャを使用したときに我々は、複数のデータを使用する場合があります場合は、次に我々は、複数のデータを保存するために、カーソルを使用する必要があります。

5.2カーソルの注意ポイントを使用します

カーソルは、ストレージまたは記憶機能の間に使用されなければならない、単独で存在することができません。

5.3カーソルを使用

構文:

1.カーソルを作成します:select文のためのカーソル名カーソルを宣言  

2.カーソル:オープンカーソル名

3.カーソルを使用します。変数名にカーソル名をFETCH

4.カーソルをクローズします:閉じるカーソル名を

5.4例

デリミタ// 
作成 機能 fun3(IDのINTは戻り INTは
、SQLデータの読み取り
開始
宣言 CUR カーソル のための 選択 stu_idをからSTU。
オープンCUR;
フェッチ CURのID。
近くCUR;
戻り値のID。
終了
//

 使用

ID = 0 @設定します。
fun3(@id)を選択します。

 

 

 結果

カーソルが変数にちょうど最初の値に見つけることができます。

 

第六に、トリガーは何ですか

トリガ条件は、トリガの定義を満たす、コレクションで定義された文を実行しながら、トリガは、テーブルに関連付けられているデータベース・オブジェクトです。この機能は、データの整合性を確保するために、データベース側でアプリケーションをトリガすることができます。

たとえば、あなたは今、このようなユーザー表[​​]と[]テーブルをログとして2つのテーブルを持っているユーザーが作成されたとき、あなたがあれば、ログログはトリガーの使用でなくて、ログテーブルに作成されて挿入する必要がありますあなたは、達成するためのプログラミング言語のロジックを記述する必要がありますが、あなたは、フリップフロップを定義する場合、フリップフロップの効果は、ユーザーテーブルにデータを挿入するときに、ログテーブルのログメッセージを挿入支援するということです。もちろん、フリップフロップだけでなく、挿入操作ですが、また、変更、削除を実行します。

トリガーの作成

次のように作成したトリガの構文は次のとおりです。

复制代码
TRIGGER_NAME trigger_time trigger_eventではtb_name作成する各列のためのtrigger_stmt ON TRIGGER 
トリガの名称:TRIGGER_NAME 
tirgger_time:トリガBEFOREのタイミング以降に
trigger_eventでは:INSERT用のトリガイベント、削除、または更新
tb_name:表現トリガが示すことである張テーブル上のトリガを確立
trigger_stmt:プロシージャの本体はトリガー、SQLステートメントまたはBEGINとに含まれるENDで複数の文することができ
、それはMySQLは以下の6つのトリガーを作成すると言うことができます:
INSERT、BEFORE DELETE、BEFORE UPDATE BEFORE 
INSERT AFTER 、AFTER UPDATE後、DELETE
复制代码

その中でも、トリガートリガー名パラメータは、名前の作成を参照します

前とトリガーパラメータは、イベントの前または後に、実行時間を指定AFTER

EACH ROWのトリガをトリガする任意のトリガ・イベントの記録に適合するように操作を指示

複数の実行文のトリガーを作成します。
トリガーイベントの後| BEFOREトリガーのトリガー名をCREATE 
FOR EACH ROWは、テーブル名ON 
BEGIN 
    文リストの実行
ENDを

ステートメントリストはセミコロンで区切り、BEGIN及び実行する複数のステートメントを表すENDパラメータ異なる文の間で実行されます、

ヒント:一般的には、MySQLのデフォルトは、文の終わりは、枝から実行されるように、競合をトリガする必要があります

     などDELIMITER、することができ、この問題解決するために:||区切り文字を、それが最後のシンボルとなって||

     トリガーが作成されたときは、区切り文字を使用することができます;となっシンボルの終わりに、

复制代码
MySQLの> DELIMITER || 
MySQLは>削除する前に、TRIGGERのデモをCREATE 
    - >ユーザの各ROW FOR 
    - > BEGIN 
    - >ログのVALUES。INSERT INTO(NOW()); 
    - >ログのVALUES INTO INSERT(NOW()); 
    - > END 
    - > || 
クエリOK、影響を受けた0行(0.06秒)

のMySQL> DELIMITER。
复制代码

上記のステートメント、終了シンボルの先頭は、||と定義され、中央のトリガ条件を定義するには、削除操作後に満足しています

||最終用途を、その後、BEGINとEND文を実行

最后使用DELIMITER ; 将结束符号还原

tigger_event:

 

load data语句是将文件的内容插入到表中,相当于是insert语句,而replace语句在一般的情况下和insert差不多,但是如果表中存在primary 或者unique索引的时候,如果插入的数据和原来的primary key或者unique相同的时候,会删除原来的数据,然后增加一条新的数据,所以有的时候执行一条replace语句相当于执行了一条delete和insert语句。

触发器可以是一条SQL语句,也可以是多条SQL代码块,那如何创建呢?

复制代码
DELIMITER $  #将语句的分隔符改为$
BEGIN
sql1;
sql2;
...
sqln
END $
DELIMITER ;  #将语句的分隔符改回原来的分号";"
复制代码

在BEGIN...END语句中也可以定义变量,但是只能在BEGIN...END内部使用:

DECLARE var_name var_type [DEFAULT value] #定义变量,可指定默认值
SET var_name = value  #给变量赋值

NEW和OLD的使用:

 

 根据以上的表格,可以使用一下格式来使用相应的数据:

NEW.columnname:新增行的某列数据
OLD.columnname:删除行的某列数据

说了这么多现在我们来创建一个触发器吧!

现在有表如下:
用户users表

复制代码
CREATE TABLEの`users`(
  ` id` int型(11)符号なしのNOT NULL AUTO_INCREMENT、
  `name`のVARCHAR(255)文字セットutf8mb4デフォルトのNULL、
  ` add_time` int型(11)DEFAULTのNULL、
  PRIMARY KEY( `id`)、
  KEY `NAME`(` NAME`(250))を用いてBTREE 
)ENGINE = MyISAMのAUTO_INCREMENT = 1000001 DEFAULT CHARSET = LATIN1。
复制代码

ログには、テーブルをログに記録します。

TABLEは`CREATE logs`(
  ` Id`はint(11)AUTO_INCREMENT NOT NULLを、
  `log` VARCHAR(255)DEFAULT NULLの'ログ説明' COMMENT、
  PRIMARY KEY(` Id`)
)ENGINEのInnoDB DEFAULT CHARSET = = = utf8mb4 COMMENT " 「テーブルを記録。

需要がある:ユーザーがログ情報にデータを挿入したときのログを生成しています。

トリガーの作成:

复制代码
DELIMITER $
CREATE TRIGGER user_log AFTER INSERT ON users FOR EACH ROW
BEGIN
DECLARE s1 VARCHAR(40)character set utf8;
DECLARE s2 VARCHAR(20) character set utf8;#后面发现中文字符编码出现乱码,这里设置字符集
SET s2 = " is created";
SET s1 = CONCAT(NEW.name,s2);     #函数CONCAT可以将字符串连接
INSERT INTO logs(log) values(s1);
END $
DELIMITER ;
复制代码

这里我用的navicat: 

查看触发器

SHOW TRIGGERS语句查看触发器信息

Tip:

上面我用的navicat直接创建,如果大家用的mysql front,name这里会有个区别,我们删除刚才的触发器,在Mysql front中测试
drop trigger  user_log;#删除触发器

打开Mysql Front:

 

mysql front在编译sql时,不用定义结尾分隔符,修改后的sql直接这样既可:

复制代码
#DELIMITER $
CREATE TRIGGER user_log AFTER INSERT ON users FOR EACH ROW
BEGIN
DECLARE s1 VARCHAR(40)character set utf8;
DECLARE s2 VARCHAR(20) character set utf8;
SET s2 = " is created";
SET s1 = CONCAT(NEW.name,s2);     #函数CONCAT可以将字符串连接
INSERT INTO logs(log) values(s1);
END #$
#DELIMITER ;
复制代码

这里再啰嗦几句:

tips:SHOW TRIGGERS语句无法查询指定的触发器

在triggers表中查看触发器信息
SELECT * FROM information_schema.triggers;

结果显示了所有触发器的详细信息,同时,该方法可以查询制定触发器的详细信息

SELECT * FROM information_schema.triggers WHERE TRIGGER_NAME='user_log';

tips:所有触发器信息都存储在information_schema数据库下的triggers表中

     可以使用SELECT语句查询,如果触发器信息过多,最好通过TRIGGER_NAME字段指定查询

回到上面,我们创建好了触发器,继续在users中插入数据并查看数据:

insert into users(name,add_time) values('周伯通',now());

好吧,我们再来查看一下logs表吧!

通过上面的例子,可以看到只需要在users中插入用户的信息,日志会自动记录到logs表中,这也许就是触发器给我带来的便捷吧!

 

限制和注意事项

触发器会有以下两种限制:

1.触发程序不能调用将数据返回客户端的存储程序,也不能使用采用CALL语句的动态SQL语句,但是允许存储程序通过参数将数据返回触发程序,也就是存储过程或者函数通过OUT或者INOUT类型的参数将数据返回触发器是可以的,但是不能调用直接返回数据的过程。

2.不能再触发器中使用以显示或隐式方式开始或结束事务的语句,如START TRANS-ACTION,COMMIT或ROLLBACK。

注意事项:MySQL的触发器是按照BEFORE触发器、行操作、AFTER触发器的顺序执行的,其中任何一步发生错误都不会继续执行剩下的操作,如果对事务表进行的操作,如果出现错误,那么将会被回滚,如果是对非事务表进行操作,那么就无法回滚了,数据可能会出错。

 

 原文出处:

https://www.cnblogs.com/SAM-CJM/p/9711458.html

https://www.cnblogs.com/phpper/p/7587031.html

 

おすすめ

転載: www.cnblogs.com/ryelqy/p/11425012.html