触发器
MySQL 5中增加了对触发器的支持。
触发器是MySQL响应以下任意语句而自动执行的一条MySQL语句(或位于BEGIN和END语句之间的一组语句)
DELETE
INSERT
UPDATE
其他MySQL语句不支持触发器
创建触发器
在创建触发器时,需要给出4条信息:
唯一的触发器名
触发器关联的表
触发器应该响应的活动(DELETE、INSERT或UPDATE)
触发器何时执行(处理之前或之后)
在MySQL5中,触发器名必须在每个表中唯一,但以后的MySQL版本可能会使命名规则更为严格,所以现在最好是在数据库范围内使用唯一的触发器名。
原书中的例子,以不能使用,如下
CREATE TRIGGER newproduct AFTER INSERT ON products
FOR EACH ROW SELECT 'Product added';
会返回错误信息:1415 - Not allowed to return a result set from a trigger
所以改成如下:
CREATE TRIGGER newproduct AFTER INSERT ON products
FOR EACH ROW SET @msg = 'Product added';
调用两个SQL语句:
INSERT INTO products (
prod_id,
vend_id,
prod_name,
prod_price,
prod_desc
)
VALUES
(
'TNT3',
1003,
'TNT (6 sticks)',
12,
'TNT, red, pack of 10 sticks'
);
SELECT @msg;
@msg来自于TRIGGER中定义的@msg
仅支持表
只有表才支持触发器,视图不支持(临时表也不支持)
触发器按每个表每个时间每次地定义,每个表每个事件每次只允许一个触发器。
因此,每个表最多支持6个触发器(每条INSERT,UPDATE,DELETE的之前和之后)
单一触发器不能与多个事件或多个表关联,所以需要一个INSERT和UPDATE操作执行的触发器,则定义两个触发器。
触发器失败
如果BEFORE触发器失败,则MySQL将不执行请求的操作。此外,如果BEFOR触发器或语句本身失败,MySQL将不执行AFTER触发器(如果有的话)
删除触发器
DROP TRIGGER newproduct;
触发器不能更新或覆盖。为了修改一个触发器,必须先删除它,然后再重新创建。
使用触发器
INSERT触发器
在INSERT触发器代码内,可引用一个名为NEW的虚拟表,访问被插入的行。
在BEFORE INSERT触发器中,NEW中的值也可以被更新(允许更改被插入的值)
对于AUTO_INCREMENT列,NEW在INSERT执行之前包含0,在INSERT执行之后包含新的自动生产值
原文范例,不适用用
CREATE TRIGGER neworder AFTER INSERT ON orders
FOR EACH ROW SELECT NEW.order_num;
改成:
CREATE TRIGGER neworder AFTER INSERT ON orders
FOR EACH ROW SET @num = NEW.order_num;
DELETE触发器
在DELETE触发器代码内,可以引用一个名为OLD的虚拟表,访问被删除的行。
OLD中的值全部都是只读的,不能更新。
CREATE TRIGGER deleteorder BEFORE DELETE ON orders FOR EACH ROW
BEGIN
INSERT INTO archive_orders (
order_num,
order_date,
cust_id
)
VALUES
(
OLD.order_num,
OLD.order_date,
OLD.cust_id
);
END;
实际使用这个例子,需要用与orders相同的列创建一个名为archive_orders的表。
使用BEGIN END块的好处是触发器能容纳多条SQL语句(在BEGIN END块中一条挨着一条)
UPDATE触发器
在UPDATE触发器代码中,可以引用一个名为OLD的虚拟表访问以前(UPDATE语句前)的值,引用一个名为NEW的虚拟表访问新更新的值。
在BEFORE UPDATE触发器中,NEW中的值可能也被更新(允许更改将要用于UPDATE语句中的值)
OLD中的值全部都是只读的,不能更新。
CREATE TRIGGER updatevendor BEFORE UPDATE ON vendors FOR EACH ROW
SET NEW.vend_state = Upper(NEW.vend_state);
每次更新一个行时,NEW.vend_state中的值(将用来更新表行的值)都用Upper(NEW.vend_state)替换
MySQL触发器不支持CALL语句,这表示不能从触发器内调用存储过程。所需要的存储过程代码需要复制到触发器内。