ホームページ  >  記事  >  データベース  >  【MySQL 12】トリガー

【MySQL 12】トリガー

黄舟
黄舟オリジナル
2017-02-04 13:40:241286ブラウズ

トリガーは特殊なタイプのストアド プロシージャであり、前に紹介したストアド プロシージャとは異なります。トリガーは主にイベントによってトリガーされ、自動的に呼び出されて実行されます。ストアド プロシージャは、ストアド プロシージャの名前で呼び出すことができます。
トリガーの主な機能は、参照整合性よりも複雑な 2 つ以上のテーブル間でデータの整合性と整合性を実現することです。これにより、テーブル内のデータの変更がデータベース設計者のルールによって決定されたビジネスに確実に準拠するようになります。
トリガーは、テーブルの挿入、更新、削除時に自動的に実行される特殊なストアド プロシージャです。トリガーは通常、より複雑なチェック制約を持つ制約で使用されます。
トリガーと通常のストアド プロシージャの違いは、トリガーが特定のテーブルに対して動作することです。更新、挿入、削除などの操作中に、システムはテーブル上の対応するトリガーを自動的に呼び出して実行します。
SQL Server 2005 のトリガーは、DML トリガーと DDL トリガーの 2 つのカテゴリに分類できます。DDL トリガーは、さまざまなデータ定義言語ステートメントに影響を与え、これらのステートメントには、create、alter、drop ステートメントがトリガーされます。

DML トリガーは次のように分類されます:

1. トリガー後 (後にトリガー)
a. トリガーの挿入
c. トリガーの代わりに (トリガー前に)
3 差分 f.トリガーは、特定の操作 (挿入、更新、削除) を実行した後にのみトリガーされる必要があり、テーブルでのみ定義できます。
定義された操作 (挿入、更新、削除) は実行されず、トリガー自体のみが実行されることを意味します。トリガーの代わりに、テーブルまたはビューにトリガーを定義できます。

挿入テーブルと削除テーブル

トリガーを使用する場合、SQL Server はトリガーごとに 2 つの特別な一時テーブル、つまり挿入テーブルと削除テーブルを作成します。これら 2 つのテーブルはメモリに保存され、トリガーが作成されたテーブルと同じ構造を持ち、システムによって維持および管理され、ユーザーは変更できません。各トリガーは、独自の一時テーブルにのみアクセスできます。トリガーの実行後、2 つのテーブルは自動的に解放されます。

(1) 挿入されたテーブルは、INSERT または UPDATE ステートメントの影響を受ける行のコピーを保存するために使用されます。挿入または更新操作が実行されると、トリガーをアクティブ化する新しいデータ行がベース テーブルと挿入テーブルの両方に追加されます。

(2) 削除されたテーブルは、削除または更新ステートメントの影響を受ける行のコピーを保存するために使用されます。削除または更新操作が実行されると、指定された元のデータ行が実表から削除され、削除された表に転送されます。一般に、実表と削除された表には同じデータ行は存在しません。

更新操作は 2 つのステップに分かれています。基本テーブルのデータ行を削除されたテーブルにコピーし、変更された新しいデータ行を挿入されたテーブルから基本テーブルにコピーします。つまり、更新操作の場合、削除されたテーブルには変更前の古い値が格納され、挿入されたテーブルには変更後の新しい値が格納されます。

トリガー作成構文の 4 つの要素:

1.监视地点(table) 
2.监视事件(insert/update/delete) 
3.触发时间(after/before) 
4.触发事件(insert/update/delete)

構文:

delimiter &&create trigger trigger
Nameafter/before insert/update/delete on 表名
for each row   #这句话在mysql是固定的
beginsql语句;
end&&

商品テーブル

mysql> create table g(
    -> id int auto_increment primary key,    -> name varchar(10),    -> num int    -> );

注文テーブル

mysql> create table o(
    -> idd int auto_increment primary key,    -> gid int,    -> much int    -> );

商品の挿入:

mysql> insert into g (name,num) value ('juzi',20);mysql> select * from g;
+----+------+------+| id | name | num  |
+----+------+------+|  3 | juzi |   20 |
+----+------+------+

トリガーを使用しなかった場合: 今、3 つの商品を販売したとします。 2 つのことを行う必要があります

1. 注文テーブルにレコードを挿入します

insert into o(gid,much) values(1,3);

2. 製品テーブルの品目 1 の残り数量を更新します

update g set num=num-3 where id=1;

トリガーを作成します:

delimiter &
mysql> create trigger trg1
    -> after insert on o    -> for each row    -> begin    -> update g set num = num -3 where id = 1;    -> end&

実行:

insert into o(gid,much) values(1,3)$

結果:

製品 1 の数量が 7 に変更されたことがわかります。これは、注文を挿入すると、トリガーが自動的に更新操作を実行することを意味します。

しかしここで問題が発生しました。トリガーの num と id がハードコーディングされているため、どの製品を購入しても、最終的には製品 1 の数量が更新されます。たとえば、別のレコードを注文テーブルに挿入します。 insert into o(gid,much) names(2,3) を実行すると、製品 1 の数量は 4 に変更されましたが、製品 2 の数量は変更されたことがわかります。これは明らかに私たちが望む結果ではありません。前に作成したトリガーを変更する必要があります。

トリガー内の行の値をどのように参照しますか。つまり、新しく挿入した注文レコード内の gid または much の値を取得する必要があります。

挿入の場合、新しく挿入された行は new で表され、行内の各列の値は new.column 名で表されます。

これでトリガーを次のように変更できるようになりました

create trigger tg2 
after insert on o 
for each row 
begin 
update g set num=num-new.much where id=new.gid;(注意此处和第一个触发器的不同) 
end$

2 番目のトリガーが作成されました。まず最初のトリガーを削除しましょう

drop トリガー tg1$

もう一度テストして注文レコードを挿入しましょう :insert into o(gid, much)values(2,3)$

実行後、製品 2 の数量が 7 に変更されていることがわかります。これは現在では正しいことです。

まだ 2 つの状況があります:

1.当用户撤销一个订单的时候,我们这边直接删除一个订单,我们是不是需要把对应的商品数量再加回去呢?

2.当用户修改一个订单的数量时,我们触发器修改怎么写?

我们先分析一下第一种情况:

监视地点:o表

监视事件:delete

触发时间:after

触发事件:update

对于delete而言:原本有一行,后来被删除,想引用被删除的这一行,用old来表示,old.列名可以引用被删除的行的值。

那我们的触发器就该这样写:

create trigger tg3
after delete on o
for each row
begin
update g set num = num + old.much where id = old.gid;(注意这边的变化)
end$

创建完毕。

再执行

delete from o where oid = 2$

会发现商品2的数量又变为10了。

第二种情况:

监视地点:o表

监视事件:update

触发时间:after

触发事件:update

对于update而言:被修改的行,修改前的数据,用old来表示,old.列名引用被修改之前行中的值;

修改的后的数据,用new来表示,new.列名引用被修改之后行中的值。

那我们的触发器就该这样写:

create trigger tg4
after update on o
for each row
begin
update g set num = num+old.much-new.much where id = old/new.gid;
end$

先把旧的数量恢复再减去新的数量就是修改后的数量了。

我们来测试下:先把商品表和订单表的数据都清掉,易于测试。

假设我们往商品表插入三个商品,数量都是10,

买3个商品1:

insert into o(gid,much) values(1,3)$

这时候商品1的数量变为7;

我们再修改插入的订单记录:

update o set much = 5 where oid = 1$

我们变为买5个商品1,这时候再查询商品表就会发现商品1的数量只剩5了,说明我们的触发器发挥作用了。

以上就是 【MySQL 12】触发器的内容,更多相关内容请关注PHP中文网(www.php.cn)!


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。