11-触发器
概述
触发器是一种特殊的存储过程,且不同于一般的存储过程。触发器主要是通过事件进行触发而被执行,而一般的存储过程则是通过存储过程名称被直接调用。
触发器是一个功能强大的工具,与表紧密连接,可以看作是表结构定义的一部分。触发器基于一个表创建,但可以操作多个表。它可以在向数据表中插入、修改或删除数据时进行检查,以保证数据完整性和一致性。当用户修改(INSERT、UPDATE或DELETE)指定表中的数据时,该表中的相应的触发器就会自动执行。
创建
- 语法
CREATE TRIGGER <触发器名>BEFORE | AFTERINSERT | UPDATE | DELETEON <表> FOR EACH ROW<触发器过程体>
- 说明
BEFORE | AFTER:触发器触发的时机。
INSERT | UPDATE | DELETE:触发器触发的事件。
FOR EACH ROW:对于触发事件影响的每一行,都要激活触发器动作。
触发器过程体:事件发生,触发器需要执行的任务。
同一张表、同一触发事件、同一触发时机只能创建一个触发器。
触发器执行的顺序BEFORE触发器、表操作(INSERT、UPDATE、DELETE)和AFTER触发器。
- 触发器中的NEW和OLD关键字
MySQL的触发器无任何输入和输出参数,其内部使用的参数就是新旧两条记录NEW和OLD的字段,用来完成数据表之间的触发操作,来保证数据库的一致性、完整性。NEW表示的新插入的数据,OLD表示的是原来的数据:
当使用INSERT语句的时候,插入的那一条数据相对于插入数据后的表来说就是NEW。
当使用DELETE语句的时候,删除的那一条数据相对于删除数据后的表来说就是OLD。
当使用UPDATE语句的时候,修改前的那一条数据相对于修改数据后的表来说就是OLD;修改后的那一条数据相对于修改数据后的表来说就是NEW。
在触发器BEFORE中可以在对NEW进行赋值和取值;而在AFTER中只能对NEW进行取值,不能赋值。
访问触发器中NEW和OLD的语法格式如下:
NEW.column_name
OLD.column_name
- 创建插入触发器
创建插入触发器使用INSERT关键字,即当指定的数据表发生数据插入操作时,自动触发并执行指定的任务;可设置在插入前触发、还是在插入后触发,分别使用BEFORE或者AFTER关键字。
示例:创建一个由INSERT触发的前触发器tr_insertStudent,一旦在学生表(student)中插入一行数据之前,检查性别是否为“男”或者“女”,如果不是,则设置为“男”。
向学生表(student)中插入一条学生记录,验证触发器tr_insertStudent。
- 创建更新触发器
创建更新触发器使用UPDATE关键字,即当指定的数据表发生数据更新操作时,自动触发并执行指定的任务;可设置在更新前触发、还是在更新后触发,分别使用BEFORE或者AFTER关键字。
示例:创建一个由UPDATE触发的后触发器tr_updateStuScore,一旦在成绩表(score)中修改了某一学生的某一课程的成绩之后,把修改时间、学号、课程编号、修改前成绩、修改后成绩保存到数据表trigger_log中。
修改成绩表(score)中的一条学生的课程成绩,验证示例9-3中的触发器tr_updateStuScore。
- 创建删除触发器
创建删除触发器使用DELETE关键字,即当指定的数据表发生数据删除操作时,自动触发并执行指定的任务;可设置在删除前触发、还是在删除后触发,分别使用BEFORE或者AFTER关键字。
示例:创建一个由DELETE触发的前触发器tr_deleteStudent,一旦在学生表(student)中删除一行数据之前,删除该学生的所有成绩记录。
删除学生表(student)中的一条学生记录,验证示例9-5中的触发器tr_deleteStudent。
练习
1)创建一个由INSERT触发的前触发器tr_insertSeller,一旦在销售员表(seller)中插入一行数据之前,检查雇佣日期是否为NULL,若为NULL,则设置为今日。然后验证该触发器。
CREATE TRIGGER tr_insertSeller
BEFORE INSERT
ON seller
FOR EACH ROW
BEGINIF NEW.hireDate IS NULL THENSET NEW.hireDate=CURRENT_DATE;END IF;
END
验证触发器
INSERT INTO seller (saleNo, saleName, sex, birthday) VALUES('s20', '王刚', '男', '1992-4-15');SELECT * FROM seller WHERE saleNo='s20';
2)创建一个由UPDATE触发的后触发器tr_updateProduct,一旦在商品表(product)中修改了某一商品的价格之后,把修改时间、当前登录用户、商品编号、修改前价格、修改后价格保存到数据表update_log中。然后验证该触发器。
CREATE TRIGGER tr_updateProduct
AFTER UPDATE
ON product
FOR EACH ROW
BEGIN INSERT update_log(exec_time, currUser, productNo, oldPrice, newPrice)VALUES(NOW(), CURRENT_USER, OLD.productNo, OLD.price, NEW.price);
END
验证触发器
#创建update_log表
CREATE TABLE IF NOT EXISTS update_log(id INT UNSIGNED NOT NULL AUTO_INCREMENT,exec_time DATETIME,currUser VARCHAR(30),productNo CHAR(6),oldPrice FLOAT(6,2),newPrice FLOAT(6,2),PRIMARY KEY (id)
) ENGINE=InnoDB;UPDATE product SET price=1.8 WHERE productNo='P03002';SELECT * FROM update_log;
3)创建一个由DELETE触发的前触发器tr_deleteSeller,一旦在销售员表(seller)中删除一行数据之前,删除该销售员的所有订单信息。然后验证该触发器。
CREATE TRIGGER tr_deleteSeller
BEFORE DELETE
ON seller
FOR EACH ROW
BEGIN DELETE FROM orderdetail WHERE orderId IN (SELECT id FROM orders WHERE saleId=OLD.id);DELETE FROM orders WHERE saleId=OLD.id;
END
验证触发器
DELETE FROM seller WHERE id=2;SELECT * FROM seller WHERE id=2;
SELECT * FROM orders WHERE saleId=2;
SELECT * FROM orderdetail WHERE orderId IN (SELECT id FROM orders WHERE saleId=2);