09-MySQL触发器

09-MySQL触发器


  • 09-MySQL触发器
    • 1 触发器简介(trigger)
    • 2 创建触发器
    • 3 创建触发器
      • 3.1 创建一个单执行语句的触发器
      • 3.2 创建有多个执行语句的触发器
    • 4 查看触发器
      • 4.1 查看triggers 表中查看触发器信息
    • 5 触发器的使用
    • 5 删除触发器
    • 6 Q&A
      • 6.1 使用触发器是注意
      • 6.2 及时删除不需要的触发器


1 触发器简介(trigger)

  1. 触发器和存储过程一样,都是嵌入到MySQL的一段程序。
  2. 触发器是由时间来出发某个操作,这些事件包括INSERT、UPDATE和DELETE语句。
  3. 定义触发器后,当数据库执行到这些语句的时候就会激发触发器执行相应的操作,触发程序是与表有关的命名数据库对象。

2 创建触发器

​ 触发器是一个特殊的存储过程,存储过程需要CALL语句进行调用,触发器的执行不需要使用CALL语句的调用。

​ 触发器可以查询其他表,而且可以包含复杂的SQL语句。它们主要用于满足复杂的业务规则或要求。例如:可以根据客户当前的账户状态,控制是否允许插入新订单。

3 创建触发器

3.1 创建一个单执行语句的触发器

语法:

create trigger trigger_name trigger_time trigger_event
on tbl_name for each row trigger_stmt

​ trigger_name是触发器名称,用户自行制定;trigger_time表示触发时机,可以指定before或者after;trigger_event 表示触发事件,包括insert ,update ,delete; tbl_name标识建立触发器的表名,即在那张表上建立触发器;trigger+stmt是触发器执行语句。

例子:创建一个单执行语句的触发器,代码如下:

-- 创建account表,表中有两个字段
create table account (acct_num int, amount decimal(10,2));

创建一个名为ins_sum的触发器,触发的条件是向数据表account插入数据之前,对新插入的数account字段值进行求和计算。

-- 创建一个名为ins_sum的触发器
create trigger ins_sum before insert on account
for each row set @sum = @sum + NEW.amount;
mysql> set @sum = 0;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into account values(1,1.00);
Query OK, 1 row affected (0.01 sec)

mysql> select @sum;
+------+
| @sum |
+------+
| 1.00 |
+------+
1 row in set (0.00 sec)

-- 插入账户数据
mysql> insert into account values(2,2.00);
Query OK, 1 row affected (0.01 sec)

-- 查询sum变量的值
mysql> select @sum;
+------+
| @sum |
+------+
| 3.00 |
+------+
1 row in set (0.00 sec)

3.2 创建有多个执行语句的触发器

语法:

create trigger trigger_name trigger_time trigger_event
on tb1_name for each row 
begin
    语句执行列表
end

​ trigger_name是触发器名称,用户自行制定;trigger_time表示触发时机,可以指定before或者after;trigger_event 表示触发事件,包括insert ,update ,delete; tbl_name标识建立触发器的表名,即在那张表上建立触发器;触发器程序可以使用begin和end作为开始和结束,中间包含多条语句。

例子:创建一个包含多个执行语句的触发器,代码如下:

创建测试表:

mysql> create table test1(a1 int);
Query OK, 0 rows affected (0.03 sec)

mysql> create table test2(a2 int);
Query OK, 0 rows affected (0.02 sec)

mysql> create table test3(a3 int not null auto_increment primary key);
Query OK, 0 rows affected (0.02 sec)

mysql> create table test4(
    -> a4 int not null auto_increment primary key,
    -> b4 int default 0
    -> );
Query OK, 0 rows affected (0.01 sec)

创建触发器:

mysql> delimiter //
mysql> create trigger testrf before insert on test1
    -> for each row begin
    -> insert into test2 set a2 = new.a1; -- 像test2插入test1的值 
    -> delete from test3 where a3 = new.a1; -- 删除test3中相同的序列
    -> update test4 set b4=b4+1 where a4 = new.a1; -- 更新test4中的b4,即插入的值相同的个数
    -> end
    -> //
Query OK, 0 rows affected (0.01 sec)

mysql> delimiter ;
mysql> insert into test3 (a3) values (null), (null), (null), (null), (null), (nu
ll), (null), (null), (null), (null);
Query OK, 10 rows affected (0.00 sec)
Records: 10  Duplicates: 0  Warnings: 0
mysql> insert into test4 (a4) values (0), (0), (0), (0), (0), (0), (0), (0), (0);
mysql> select * from test4;
+----+------+
| a4 | b4   |
+----+------+
|  1 |    0 |
|  2 |    0 |
|  3 |    0 |
|  4 |    0 |
|  5 |    0 |
|  6 |    0 |
|  7 |    0 |
|  8 |    0 |
|  9 |    0 |
+----+------+
9 rows in set (0.00 sec)

mysql> select * from test3;
+----+
| a3 |
+----+
|  1 |
|  2 |
|  3 |
|  4 |
|  5 |
|  6 |
|  7 |
|  8 |
|  9 |
| 10 |
+----+
10 rows in set (0.00 sec)

mysql> select * from test2;
Empty set (0.00 sec)

mysql> select * from test1;
Empty set (0.00 sec)
mysql> insert into test1 values (1),(3),(1),(7),(1),(8),(4),(4);
Query OK, 8 rows affected (0.01 sec)
Records: 8  Duplicates: 0  Warnings: 0
mysql> select * from test1;
+------+
| a1   |
+------+
|    1 |
|    3 |
|    1 |
|    7 |
|    1 |
|    8 |
|    4 |
|    4 |
+------+
8 rows in set (0.00 sec)

-- 向test2插入test1的值
mysql> select * from test2;
+------+
| a2   |
+------+
|    1 |
|    3 |
|    1 |
|    7 |
|    1 |
|    8 |
|    4 |
|    4 |
+------+
8 rows in set (0.00 sec)

-- 删除test3中相同的序列
mysql> select * from test3;
+----+
| a3 |
+----+
|  2 |
|  5 |
|  6 |
|  9 |
| 10 |
+----+
5 rows in set (0.00 sec)

-- 更新test4中的b4,即插入的值相同的个数
mysql> select * from test4;
+----+------+
| a4 | b4   |
+----+------+
|  1 |    3 |
|  2 |    0 |
|  3 |    1 |
|  4 |    2 |
|  5 |    0 |
|  6 |    0 |
|  7 |    1 |
|  8 |    1 |
|  9 |    0 |
+----+------+
9 rows in set (0.00 sec)

4 查看触发器

mysql> show triggers \G;
*************************** 1. row ***************************
             Trigger: ins_sum
               Event: INSERT
               Table: account
           Statement: set @sum= @sum+new.account
              Timing: BEFORE
             Created: 2018-05-01 18:16:44.22
            sql_mode: STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITU
TION
             Definer: root@localhost
character_set_client: utf8
collation_connection: utf8_general_ci
  Database Collation: utf8_general_ci
*************************** 2. row ***************************
             Trigger: testrf
               Event: INSERT
               Table: test1
           Statement: begin
insert into test2 set a2 = new.a1;
delete from test3 where a3 = new.a1;
update test4 set b4=b4+1 where a4 = new.a1;
end
              Timing: BEFORE
             Created: 2018-05-01 18:30:50.90
            sql_mode: STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITU
TION
             Definer: root@localhost
character_set_client: utf8
collation_connection: utf8_general_ci
  Database Collation: utf8_general_ci
2 rows in set (0.00 sec)
参数 备注
Trigger 触发器名称
Event 激活触发器的时间
Table 触发器作用的表
Statement 触发器执行的操作
Timing 触发器执行的时间

4.1 查看triggers 表中查看触发器信息

-- 语法
select * from information_schema.triggers where condition;
mysql> select * from information_schema.triggers where trigger_name= 'ins_sum' \
G;
*************************** 1. row ***************************
           TRIGGER_CATALOG: def
            TRIGGER_SCHEMA: test
              TRIGGER_NAME: ins_sum
        EVENT_MANIPULATION: INSERT
      EVENT_OBJECT_CATALOG: def
       EVENT_OBJECT_SCHEMA: test
        EVENT_OBJECT_TABLE: account
              ACTION_ORDER: 1
          ACTION_CONDITION: NULL
          ACTION_STATEMENT: set @sum= @sum+new.account
        ACTION_ORIENTATION: ROW
             ACTION_TIMING: BEFORE
ACTION_REFERENCE_OLD_TABLE: NULL
ACTION_REFERENCE_NEW_TABLE: NULL
  ACTION_REFERENCE_OLD_ROW: OLD
  ACTION_REFERENCE_NEW_ROW: NEW
                   CREATED: 2018-05-01 18:16:44.22
                  SQL_MODE: STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SU
BSTITUTION
                   DEFINER: root@localhost
      CHARACTER_SET_CLIENT: utf8
      COLLATION_CONNECTION: utf8_general_ci
        DATABASE_COLLATION: utf8_general_ci
1 row in set (0.06 sec)

ERROR:
No query specified

5 触发器的使用

​ 触发程序是与表有关的命名数据库对象,当表上出现特定事件时,将激活该对象,在某些触发程序的用法中,可用于检查插入到表中的值,或最更新涉及的值进行计算。

​ 触发程序与表相关,当对表执行insert、delete 、update语句时,将激活触发程序,可以将触发程序设置为在执行特定之前或者之后。

例子:创建一个account表插入记录后,更新myevent数据表的触发器,代码如下:

mysql> create trigger trig_insert after insert on account
    -> for each row insert into  myevent values(2,'after insert');
Query OK, 0 rows affected (0.01 sec)
mysql> create trigger trig_insert after insert on account
    -> for each row insert into  myevent values(2,'after insert');
Query OK, 0 rows affected (0.01 sec)

mysql> insert into account values (1,1.00),(2,2.00);
ERROR 1146 (42S02): Table 'test.myevent' doesn't exist
mysql> create table myevent (
    -> id int ,
    -> name varchar(20)
    -> );
Query OK, 0 rows affected (0.03 sec)

mysql> insert into account values (1,1.00),(2,2.00);
Query OK, 2 rows affected (0.01 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> select * from myevent;
+------+--------------+
| id   | name         |
+------+--------------+
|    2 | after insert |
|    2 | after insert |
+------+--------------+
2 rows in set (0.00 sec)

5 删除触发器

语法:

drop trigger [schema_name] trigger_name

schema_name为数据库名,可选,trigger_name 是要删除的触发器的名称。

drop trigger test.ins;

6 Q&A

6.1 使用触发器是注意

​ 如果已经对一个表创建了before insert ,那么再创建before insert时就会报错

6.2 及时删除不需要的触发器

​ 触发器定义后,每次执行触发操作,都会激活触发器并执行触发器中的语句。如果需求发生变化,而触发器没有进行相应的改变或者删除,则触发器依然会执行旧的语句,从而影响新的数据的完整性。因此要将不再使用的触发器及时删除。

你可能感兴趣的:(MySQL)