当前位置:嗨网首页>书籍在线阅读

02-创建触发器

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

创建触发器的语法如下:

CREATE TRIGGER trigger_name trigger_time trigger_event

ON tbl_name FOR EACH ROW trigger_stmt

注意:触发器只能创建在永久表(Permanent Table)上,不能对临时表(Temporary Table)创建触发器。

其中trigger_time是触发器的触发时间,可以是BEFORE或者AFTER,BEFORE的含义指在检查约束前触发,而AFTER是在检查约束后触发。

而trigger_event就是触发器的触发事件,可以是INSERT、UPDATE或者DELETE。

对同一个表相同触发时间的相同触发事件,只能定义一个触发器。例如,对某个表的不同字段的AFTER更新触发器,在使用Oracle数据库的时候,可以定义成两个不同的UPDATE触发器,更新不同的字段时触发单独的触发器,但是在MYSQL数据库中,只能定义成一个触发器,在触发器中通过判断更新的字段进行对应的处理。

使用别名 OLD 和 NEW 来引用触发器中发生变化的记录内容,这与其他的数据库是相似的。现在触发器还只支持行级触发,不支持语句级触发。

在样例数据库中,为 film表创建了AFTER INSERT的触发器,具体如下:

DELIMITER $$

CREATE TRIGGER ins_film

AFTER INSERT ON film FOR EACH ROW BEGIN

INSERT INTO film_text (film_id, title, description)

VALUES (new.film_id, new.title, new.description);

END;

$$

delimiter ;

插入film表记录的时候,会向film_text表中也插入相应的记录。

mysql> INSERT INTO film VALUES

-> (1001,'ACADEMY DINOSAUR',

-> 'A Epic Drama of a Feminist And a Mad Scientist who must Battle a Teacher in The Canadian Rockies',

-> 2006,1,NULL,6,'0.99',86,'20.99','PG','Deleted Scenes,Behind the Scenes', '2006-02-15 05:03:42');

Query OK, 1 row affected (0.05 sec)

mysql> select * from film_text where film_id=1001 \G

1. row

film_id: 1001

title: ACADEMY DINOSAUR

description: A Epic Drama of a Feminist And a Mad Scientist who must Battle a Teacher in The Canadian Rockies

1 row in set (0.00 sec)

对于 INSERT INTO…ON DUPLICATE KEY UPDATE…语句来说,触发触发器的顺序可能会造成疑惑。下面对 film表分别创建了BEFORE INSERT、AFTER INSERT、BEFORE UPDATE、AFTER UPDATE触发器,然后插入记录,观察触发器的触发情况:

--创建BEFORE INSERT、AFTER INSERT、BEFORE UPDATE、AFTER UPDATE触发器:

mysql> create table tri_demo(id int AUTO_INCREMENT,note varchar(20),PRIMARY KEY (id));

Query OK, 0 rows affected (0.03 sec)

mysql> CREATE TRIGGER ins_film_bef

-> BEFORE INSERT ON film FOR EACH ROW BEGIN

-> INSERT INTO tri_demo (note) VALUES ('before insert');

-> END;

-> $$

Query OK, 0 rows affected (0.00 sec)

mysql> CREATE TRIGGER ins_film_aft

-> AFTER INSERT ON film FOR EACH ROW BEGIN

-> INSERT INTO tri_demo (note) VALUES ('after insert');

-> END;

-> $$

Query OK, 0 rows affected (0.00 sec)

mysql> CREATE TRIGGER upd_film_bef

-> BEFORE update ON film FOR EACH ROW BEGIN

-> INSERT INTO tri_demo (note) VALUES ('before update');

-> END;

-> $$

Query OK, 0 rows affected (0.00 sec)

mysql> CREATE TRIGGER upd_film_aft

-> AFTER update ON film FOR EACH ROW BEGIN

-> INSERT INTO tri_demo (note) VALUES ('after update');

-> END;

-> $$

Query OK, 0 rows affected (0.00 sec)

--插入记录已经存在的情况

mysql> select film_id,title from film where film_id = 1001;

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

| film_id | title |

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

| 1001 | ACADEMY DINOSAUR |

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

1 row in set (0.00 sec)

mysql> INSERT INTO film VALUES

-> (1001,'Only test',

-> 'Only test',2006,1,NULL,6,'0.99',86,'20.99','PG',

-> 'Deleted Scenes,Behind the Scenes','2006-02-15 05:03:42')

-> ON DUPLICATE KEY

-> UPDATE title='update record';

Query OK, 2 rows affected (0.05 sec)

mysql> select * from tri_demo;

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

| id | note|

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

| 1 | before insert |

| 2 | before update |

| 3 | after update |

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

3 rows in set (0.00 sec)

--插入新记录的情况

mysql> delete from tri_demo;

Query OK, 3 rows affected (0.00 sec)

mysql> select film_id,title from film where film_id = 1002;

Empty set (0.00 sec)

mysql> INSERT INTO film VALUES

-> (1002,'Only test',

-> 'Only test',2006,1,NULL,6,'0.99',86,'20.99','PG',

-> 'Deleted Scenes,Behind the Scenes','2006-02-15 05:03:42')

-> ON DUPLICATE KEY

-> UPDATE title='update record';

Query OK, 1 row affected (0.05 sec)

mysql>

mysql> select * from tri_demo;

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

| id | note|

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

| 4 | before insert |

| 5 | after insert |

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

2 rows in set (0.00 sec)

从上面的例子可以知道,对于有重复记录、需要进行UPDATE操作的INSERT,触发器触发的顺序是 BEFORE INSERT、BEFORE UPDATE、AFTER UPDATE;对于没有重复记录的INSERT,就是简单地执行 INSERT 操作,触发器触发的顺序是 BEFORE INSERT、AFTER INSERT。对于那些实际执行UPDATE操作的记录,仍然会执行BEFORE INSERT触发器的内容,在设计触发器的时候一定要考虑这种情况,避免错误地触发了触发器。