触发器的作用

触发器是自动化的SQL程序,由插入、更新和删除事件来触发。

当面对复杂的业务关系,在程序上难以实现时。

当程序上实现较为复杂,希望在数据库内实现时。

 

 

触发器的语法

CREATE TRIGGER  <触发器名称>

{BEFORE|AFTER}

{INSERT |UPDATE |DELETE}

ON <表名称>

FOR EATH ROW

<触发器SQL语句>

 

创建简单的触发器

 

创建数据库

mysql> use db1;

ERROR 1049 (42000): Unknown database 'db1'

mysql> create database db1;

Query OK, 1 row affected (0.07 sec)

 

使用数据库

mysql> use db1;

Database changed

mysql> show tables;

Empty set (0.00 sec)

 

创建表

mysql> create table t1 ( id int, namevarchar(10), salary int );

Query OK, 0 rows affected (0.05 sec)

 

查看表结构

mysql> desc t1;

+--------+-------------+------+-----+---------+-------+

| Field | Type        | Null | Key |Default | Extra |

+--------+-------------+------+-----+---------+-------+

| id    | int(11)     | YES  |     |NULL    |       |

| name  | varchar(10) | YES  |     | NULL   |       |

| salary | int(11)     | YES |     | NULL    |      |

+--------+-------------+------+-----+---------+-------+

3 rows in set (0.09 sec)

 

创建表

mysql> create table t2 (

   -> user_total int,

   -> salary_total int

   -> );

Query OK, 0 rows affected (0.05 sec)

 

查看表结构

mysql> desc t2;

+--------------+---------+------+-----+---------+-------+

| Field        | Type    | Null | Key | Default | Extra |

+--------------+---------+------+-----+---------+-------+

| user_total   | int(11) | YES  |     |NULL    |       |

| salary_total | int(11) | YES  |     |NULL    |       |

+--------------+---------+------+-----+---------+-------+

2 rows in set (0.00 sec)

 

 

 

插入数据

mysql> insert into t1 values (1,'jingjing',3000),

(2,'Lee',2000),

(3,'Tom',5000),

(4,'Lily',7000),

(5,'July',1000);

Query OK, 5 rows affected (0.03 sec)

Records: 5 Duplicates: 0  Warnings: 0

 

查看数据

mysql> select * from t1;

+------+----------+--------+

| id  | name     | salary |

+------+----------+--------+

|   1 | jingjing |   3000 |

|   2 | Lee      |   2000 |

|   3 | Tom      |   5000 |

|   4 | Lily     |   7000 |

|   5 | July     |   1000 |

+------+----------+--------+

5 rows in set (0.00 sec)

 

T2表插入数据

mysql> insert into t2 selectcount(*),sum(salary) from t1;

Query OK, 1 row affected (0.01 sec)

Records: 1 Duplicates: 0  Warnings: 0

mysql> select * from t2;

+------------+--------------+

| user_total | salary_total |

+------------+--------------+

|         5 |        18000 |

+------------+--------------+

1 row in set (0.00 sec)

 

 

 

创建触发器

mysql> create trigger t1_ai after inserton t1 for each row update t2 set user_total=user_total+1,salary_total=salary_total+new.salary;

Query OK, 0 rows affected (0.02 sec)

 

 

mysql> select * from t1;

+------+----------+--------+

| id  | name     | salary |

+------+----------+--------+

|   1 | jingjing |   3000 |

|   2 | Lee      |   2000 |

|   3 | Tom      |   5000 |

|   4 | Lily     |   7000 |

|   5 | July     |   1000 |

+------+----------+--------+

5 rows in set (0.00 sec)

 

mysql> select * from t2;

+------------+--------------+

| user_total | salary_total |

+------------+--------------+

|         5 |        18000 |

+------------+--------------+

1 row in set (0.00 sec)

 

 

 

T1表增加了一条数据

mysql> insert into t1 values(6,'jack',2000);

Query OK, 1 row affected (0.00 sec)

 

T2表数据发生了变化。

 

mysql> select * from t2;

+------------+--------------+

| user_total | salary_total |

+------------+--------------+

|         6 |        20000 |

+------------+--------------+

1 row in set (0.00 sec)

 

 

创建触发器2

 

mysql> create trigger t1_ad

   -> after delete on t1

   -> for each row

   -> update t2 set

   -> user_total=user_total-1,

   -> salary_total=salary_total-old.salary;

Query OK, 0 rows affected (0.01 sec)

 

mysql> select * from t1;

+------+----------+--------+

| id  | name     | salary |

+------+----------+--------+

|   1 | jingjing |   3000 |

|   2 | Lee      |   2000 |

|   3 | Tom      |   5000 |

|   4 | Lily     |   7000 |

|   5 | July     |   1000 |

|   6 | jack     |   2000 |

+------+----------+--------+

6 rows in set (0.00 sec)

 

mysql> select * from t2;

+------------+--------------+

| user_total | salary_total |

+------------+--------------+

|         6 |        20000 |

+------------+--------------+

1 row in set (0.00 sec)

 

删除一行数据

mysql> delete from t1 where id=6;

Query OK, 1 row affected (0.05 sec)

 

mysql> select * from t1;

+------+----------+--------+

| id  | name     | salary |

+------+----------+--------+

|   1 | jingjing |   3000 |

|   2 | Lee      |   2000 |

|   3 | Tom      |   5000 |

|   4 | Lily     |   7000 |

|   5 | July     |   1000 |

+------+----------+--------+

5 rows in set (0.00 sec)

 

mysql> select * from t2;

+------------+--------------+

| user_total | salary_total |

+------------+--------------+

|         5 |        18000 |

+------------+--------------+

1 row in set (0.00 sec)

 

 

创建触发器

 

mysql> create trigger t1_au after updateon t1 for each row update t2 set salary_total=salary_total-old.salary+new.salary;

Query OK, 0 rows affected (0.00 sec)

 

 

mysql> select * from t1;

+------+----------+--------+

| id  | name     | salary |

+------+----------+--------+

|   1 | jingjing |   3000 |

|   2 | Lee      |   2000 |

|   3 | Tom      |   5000 |

|   4 | Lily     |   7000 |

|   5 | July     |   1000 |

+------+----------+--------+

5 rows in set (0.00 sec)

 

mysql> select * from t2;

+------------+--------------+

| user_total | salary_total |

+------------+--------------+

|         5 |        18000 |

+------------+--------------+

1 row in set (0.00 sec)

 

更新数据

mysql> update t1 set salary=2000 whereid=5;

Query OK, 1 row affected (0.01 sec)

Rows matched: 1  Changed: 1 Warnings: 0

 

查看

mysql> select * from t2;

+------------+--------------+

| user_total | salary_total |

+------------+--------------+

|         5 |        19000 |

+------------+--------------+

1 row in set (0.00 sec)

 

同一个事件无法创建两个以上的触发器。

 

如果想创建两个可以用after和before的方式。

After update  on  T1 表示 T1更新之后触发T2。

Before update on   T1表示T1更新之前触发T2。

 

事件和触发器影响的事件在同一个事物里面。因此不会出现数据不一致的情况。

 

 

 

创建多执行语句触发器

 

Begin和end

 

加入了判断语句,统称为流控制语句

 

使用IF语句的触发器1

mysql> create table t3 (

   -> id int,

   -> name varchar(10),

   -> gid int

   -> );

Query OK, 0 rows affected (0.04 sec)

 

mysql>

mysql>

mysql> create table t4 (

   -> user_total int,

   -> vip_total int

   -> );

Query OK, 0 rows affected (0.05 sec)

 

mysql> insert into t3 values

   -> (1,'joe',0),

   -> (2,'Ken',1),

   -> (3,'Norman',0),

   -> (4,'Tobb',0),

    -> (5,'July',1),

   -> (6,'Zen',1),

   -> (7,'Bob',0),

   -> (8,'Mars',1),

   -> (9,'Tom',0),

   -> (10,'Lee',0);

Query OK, 10 rows affected (0.04 sec)

Records: 10 Duplicates: 0  Warnings: 0

 

mysql> select * from t3;

+------+--------+------+

| id  | name   | gid  |

+------+--------+------+

|   1 | joe    |    0 |

|   2 | Ken    |    1 |

|   3 | Norman |    0 |

|   4 | Tobb   |    0 |

|   5 | July   |    1 |

|   6 | Zen    |    1 |

|   7 | Bob    |    0 |

|   8 | Mars   |    1 |

|   9 | Tom    |    0 |

|  10 | Lee    |    0 |

+------+--------+------+

10 rows in set (0.00 sec)

 

 

mysql> insert into t4 values (6,4);

Query OK, 1 row affected (0.00 sec)

 

 

 

mysql> select * from t3;

+------+--------+------+

| id  | name   | gid  |

+------+--------+------+

|   1 | joe    |    0 |

|   2 | Ken    |    1 |

|   3 | Norman |    0 |

|   4 | Tobb   |    0 |

|   5 | July   |    1 |

|   6 | Zen    |    1 |

|   7 | Bob    |    0 |

|   8 | Mars   |    1 |

|   9 | Tom    |    0 |

|  10 | Lee    |    0 |

+------+--------+------+

10 rows in set (0.00 sec)

 

mysql> select * from t4;

+------------+-----------+

| user_total | vip_total |

+------------+-----------+

|         6 |         4 |

+------------+-----------+

1 row in set (0.00 sec)

 

创建触发器

mysql> delimiter //      把SQL语句的结束符改成//

mysql> create trigger t3_ai

   -> after insert on t3

   -> for each row

   -> if new.gid=0 then

   -> update t4 set user_total=user_total+1;

   -> else update t4 set vip_total=vip_total+1;

   -> end if;

   -> //

Query OK, 0 rows affected (0.01 sec)

 

mysql> delimiter ;    把SQL语句的结束符改为;

 

 

mysql> select * from t3;

+------+--------+------+

| id  | name   | gid  |

+------+--------+------+

|   1 | joe    |    0 |

|   2 | Ken    |    1 |

|   3 | Norman |    0 |

|   4 | Tobb   |    0 |

|   5 | July   |    1 |

|   6 | Zen    |    1 |

|   7 | Bob    |    0 |

|   8 | Mars   |    1 |

|   9 | Tom    |    0 |

|  10 | Lee    |    0 |

+------+--------+------+

10 rows in set (0.00 sec)

 

mysql> select * from t4;

+------------+-----------+

| user_total | vip_total |

+------------+-----------+

|         6 |         4 |

+------------+-----------+

1 row in set (0.00 sec)

 

更新数据

mysql> insert into t3 values(11,'jing',0);

Query OK, 1 row affected (0.01 sec)

 

查看

mysql> select * from t3;

+------+--------+------+

| id  | name   | gid  |

+------+--------+------+

|   1 | joe    |    0 |

|   2 | Ken    |    1 |

|   3 | Norman |    0 |

|   4 | Tobb   |    0 |

|   5 | July   |    1 |

|   6 | Zen    |    1 |

|   7 | Bob    |    0 |

|   8 | Mars   |    1 |

|   9 | Tom    |    0 |

|  10 | Lee    |    0 |

|  11 | jing   |    0 |

+------+--------+------+

11 rows in set (0.00 sec)

 

mysql> select * from t4;

+------------+-----------+

| user_total | vip_total |

+------------+-----------+

|         7 |         4 |

+------------+-----------+

1 row in set (0.00 sec)

 

使用IF语句的触发器2

mysql> delimiter //

mysql>create trigger t3_ad after deleteon t3 for each row if old.gid=0 then update t4 set user_total=user_total-1; elseupdate t4 set vip_total=vip_total-1; end if;//

mysql> delimiter ;

 

使用IF语句的触发器3

mysql> delimiter //

mysql>create trigger t3_au after updateon t3 for each row if new.gid!=old.gid and new.gid=0 then update t4 setuser_total=user_total+1,vip_total=vip_total-1; else new.gid!=old.gid andnew.gid=1 then update t4 set user_total=user_total-1,vip_total=vip_total+1; endif;//

mysql> delimiter ;

 

 

 

使用CASE语句的触发器1

mysql> delimiter //

mysql>create trigger t3_au after updateon t3 for each row CASE WHEN new.gid!=old.gid and new.gid=0 then update t4 setuser_total=user_total+1,vip_total=vip_total-1; WHEN new.gid!=old.gid andnew.gid=1 then update t4 set user_total=user_total-1,vip_total=vip_total+1; endcase;//

mysql> delimiter ;

 

 

 

mysql> select * from t3;

+------+--------+------+

| id  | name   | gid  |

+------+--------+------+

|   1 | joe    |    0 |

|   2 | Ken    |    1 |

|   3 | Norman |    0 |

|   4 | Tobb   |    0 |

|   5 | July   |    1 |

|   6 | Zen    |    1 |

|   7 | Bob    |    0 |

|   8 | Mars   |    1 |

|   9 | Tom    |    0 |

|  10 | Lee    |    0 |

|  11 | jing   |    0 |

+------+--------+------+

11 rows in set (0.01 sec)

 

mysql> select * from t4;

+------------+-----------+

| user_total | vip_total |

+------------+-----------+

|          7 |         4 |

+------------+-----------+

1 row in set (0.00 sec)

 

mysql> update t3 set gid=1 where id=11;

Query OK, 1 row affected (0.02 sec)

Rows matched: 1  Changed: 1 Warnings: 0

 

mysql> select * from t4;

+------------+-----------+

| user_total | vip_total |

+------------+-----------+

|         6 |         5 |

+------------+-----------+

1 row in set (0.00 sec)

 

 

使用CASE语句的触发器2

 

mysql> delimiter //

mysql>create trigger t3_ad after deleteon t3 for each row CASE WHEN old.gid=0 then update t4 set user_total=user_total-1;WHEN old.gid=1 then update t4 set vip_total=vip_total-1; end case;//

mysql> delimiter ;

 

 

mysql> select * from t3;

+------+--------+------+

| id  | name   | gid  |

+------+--------+------+

|   1 | joe    |    0 |

|   2 | Ken    |    1 |

|   3 | Norman |    0 |

|   4 | Tobb   |    0 |

|   5 | July   |    1 |

|   6 | Zen    |    1 |

|   7 | Bob    |    0 |

|   8 | Mars   |    1 |

|   9 | Tom    |    0 |

|  10 | Lee    |    0 |

|  11 | jing   |    1 |

+------+--------+------+

11 rows in set (0.00 sec)

 

mysql> select * from t4;

+------------+-----------+

| user_total | vip_total |

+------------+-----------+

|         6 |         5 |

+------------+-----------+

1 row in set (0.00 sec)

 

mysql> delete from t3 where id=11;

Query OK, 1 row affected (0.00 sec)

 

mysql> select * from t4;

+------------+-----------+

| user_total | vip_total |

+------------+-----------+

|         6 |         4 |

+------------+-----------+

1 row in set (0.00 sec)

 

使用loop语句的触发器1   

 

每次选取一个随机值

mysql> select id,name,gid from t3 orderby rand() limit 1;

+------+------+------+

| id  | name | gid  |

+------+------+------+

|   6 | Zen  |    1 |

+------+------+------+

1 row in set (0.00 sec)

 

 

T3表ID列加索引

mysql> alter table t3 add index (id);

Query OK, 0 rows affected (0.13 sec)

Records: 0 Duplicates: 0  Warnings: 0

 

Rand()依然是全表扫描

mysql> explain select id,name,gid fromt3 order by rand() limit 1\G;

*************************** 1. row***************************

          id: 1

 select_type: SIMPLE

       table: t3

  partitions: NULL

        type: ALL

possible_keys: NULL

         key: NULL

     key_len: NULL

         ref: NULL

        rows: 10

    filtered: 100.00

       Extra: Using temporary; Using filesort

1 row in set, 1 warning (0.00 sec)

 

ERROR:

No query specified

 

 

 

创建表

mysql> create table t5 (

   -> event_date date,

   -> wnnum int

   -> );

Query OK, 0 rows affected (0.05 sec)

 

mysql> create table t6 (

   -> id int,

   -> name varchar(10),

   -> gid int,

   -> event_date date

   -> );

Query OK, 0 rows affected (0.04 sec)

 

mysql> desc t5;

+------------+---------+------+-----+---------+-------+

| Field     | Type    | Null | Key | Default |Extra |

+------------+---------+------+-----+---------+-------+

| event_date | date    | YES |     | NULL    |      |

| wnnum     | int(11) | YES  |     | NULL   |       |

+------------+---------+------+-----+---------+-------+

2 rows in set (0.00 sec)

 

mysql> desc t6;

+------------+-------------+------+-----+---------+-------+

| Field     | Type        | Null | Key |Default | Extra |

+------------+-------------+------+-----+---------+-------+

| id        | int(11)     | YES |     | NULL    |      |

| name      | varchar(10) | YES  |     | NULL   |       |

| gid       | int(11)     | YES  |     |NULL    |       |

| event_date | date        | YES |     | NULL    |      |

+------------+-------------+------+-----+---------+-------+

4 rows in set (0.00 sec)

 

 

触发器

mysql> create trigger t5_ai after inserton t5 for each row begin declare mnum int default 0;

   -> declare wnum int;

   -> declare tnum int;

   -> declare rnum int;

   -> declare tdate date;

   -> select count(*) into tnum from t3;

   -> set tdate=new.event_date;

   -> set wnum=new.wnnum;

   -> t5_loop:loop

   -> set mnum=mnum+1;

   -> set rnum=floor(1+rand()*tnum);

   -> insert into t6 select id,name,gid,tdate from t3 where id=rnum;

   -> if mnum>=wnum

   -> then leave t5_loop;

   -> end if;

   -> end loop t5_loop;

   -> end;

   -> //

Query OK, 0 rows affected (0.01 sec)

 

查看

mysql> select * from t5;

Empty set (0.01 sec)

 

mysql> select * from t6;

Empty set (0.00 sec)

 

插入数据

mysql> insert into t5 values('2014-3-2',3);

Query OK, 1 row affected (0.12 sec)

 

查看t6表

mysql> select * from t6;

+------+--------+------+------------+

| id  | name   | gid  | event_date |

+------+--------+------+------------+

|   2 | Ken    |    1 | 2014-03-02 |

|   3 | Norman |    0 | 2014-03-02 |

|   7 | Bob    |    0 | 2014-03-02 |

+------+--------+------+------------+

3 rows in set (0.00 sec)

 

使用Repeat语句的触发器1

mysql> create trigger t5_ai after inserton t5 for each row begin declare mnum int default 0;

   -> declare wnum int;

   -> declare tnum int;

   -> declare rnum int;

   -> declare tdate date;

   -> select count(*) into tnum from t3;

   -> set tdate=new.event_date;

   -> set wnum=new.wnnum;

-> Repeat

-> Set mnum=mnum+1;

-> Set rnum=floor(1+rand()*tnum);

-> Insert into t6 select id,name,gid,tdate

-> From t3 where id=rnum;

-> Until mnum>=wnum

-> End repeat;

-> End;

-> //

此循环语句比LOOP简便。

 

使用while语句的触发器1

mysql> create trigger t5_ai after inserton t5 for each row begin declare mnum int default 0;

   -> declare wnum int;

   -> declare tnum int;

   -> declare rnum int;

   -> declare tdate date;

   -> select count(*) into tnum from t3;

   -> set tdate=new.event_date;

   -> set wnum=new.wnnum;

-> while mnum<wnum

-> Set mnum=mnum+1;

-> Set rnum=floor(1+rand()*tnum);

-> Insert into t6 select id,name,gid,tdate

-> From t3 where id=rnum;

-> end while;

-> End;

-> //

While循环语句最简单

 

查看触发器

 

mysql> show triggers\G;

 

这种可以指定显示

mysql> select * frominformation_schema.triggers where TRIGGER_NAME='t1_ai'\G;

*************************** 1. row***************************

          TRIGGER_CATALOG: def

           TRIGGER_SCHEMA: db1

              TRIGGER_NAME: t1_ai

       EVENT_MANIPULATION: INSERT

     EVENT_OBJECT_CATALOG: def

      EVENT_OBJECT_SCHEMA: db1

       EVENT_OBJECT_TABLE: t1

              ACTION_ORDER: 1

         ACTION_CONDITION: NULL

         ACTION_STATEMENT: update t2 set user_total=user_total+1,salary_total=salary_total+new.salary

       ACTION_ORIENTATION: ROW

            ACTION_TIMING: AFTER

ACTION_REFERENCE_OLD_TABLE: NULL

ACTION_REFERENCE_NEW_TABLE: NULL

 ACTION_REFERENCE_OLD_ROW: OLD

 ACTION_REFERENCE_NEW_ROW: NEW

                   CREATED: 2016-01-2816:14:11.22

                  SQL_MODE:ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

                   DEFINER: root@localhost

     CHARACTER_SET_CLIENT: utf8

     COLLATION_CONNECTION: utf8_general_ci

       DATABASE_COLLATION: latin1_swedish_ci

1 row in set (0.02 sec)

 

ERROR:

No query specified

 

删除触发器

 

Drop  trigger  trigger_name;

 



转载于:https://blog.51cto.com/sunshinesnail/1739862