暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

SQL_触发器

lin在路上 2020-08-17
362

之前介绍的语句和存储过程,都需要被执行。而触发器用于当条件满足时自动执行某条语句或某些语句,比如顾客表插入时自动检查电话格式是否正确,订购产品时从库存中减去订购的数量等。

1 触发器

建议尽量少用触发器,如果有更好的方法最好不用触发器。因为触发器是针对每一行的;若是对增删改非常频繁的表上使用触发器,它将会非常消耗资源。

1.1 创建触发器

 CREATE TRIGGER 触发器名 BEFORE|AFTER 触发事件
 ON 表名 FOR EACH ROW
 BEGIN
    执行语句列表
 END;
 
 -- 触发器名必须唯一
 -- 只有表才支持触发器,视图不支持触发器
 -- 触发事件支持INSERT、DELETE、UPDATE三种操作,支持AFTER、BEFORE两种触发时间
 -- BEGIN..END用于封装执行语句列表,若执行语句只有一条则可以省略
 -- 5.7之后引入trigger_order,用于定义多个触发器,使用follows和precedes来选择触发器执行的先后顺序
复制

1.2 查询触发器

 SHOW TRIGGERS;
 -- 显示所有触发器
 
 SELECT * FROM information_schema.`TRIGGERS`
复制

1.3 删除触发器

 DROP TRIGGER 触发器名;
 -- 触发器不支持更新或覆盖,若需要修改,必须先删除
复制

2 INSERT型触发器

插入某一行时激活触发器,可能通过INSERT、LOAD DATA、REPLACE 语句触发(LOAD DAT语句用于将一个文件装入到一个数据表中,相当一系列的INSERT操作)。

可以用NEW.columnName获取将要(BEFORE)或已经(AFTER)插入的新数据,NEW可以使用SET进行赋值而又不触发触发器,从而导致循环调用。

 CREATE TABLE IF NOT EXISTS account (acct_num INT, amount DECIMAL(10,2));
 TRUNCATE TABLE account;
 -- 创建表(若表不存在)并清空
 
 delimiter $$
 CREATE TRIGGER ins_check BEFORE INSERT ON account
 FOR EACH ROW
 BEGIN
 IF NEW.amount < 0 THEN
  SET NEW.amount = 0;
 ELSEIF NEW.amount > 100 THEN
  SET NEW.amount = 100;
 END IF;
 END$$
 delimiter ;
 -- 创建触发器,若插入的amount<0则改为0;>100则改为100
 -- AFTER不能对NEW进行修改,BEFORE可以对NEW进行修改
 
 INSERT INTO account VALUES(137,14.98),(141,1937.50),(97,-100.00);
 select * from account;
 -- 插入数据并验证效果
 
 DROP TRIGGER ins_check;
 -- 使用完建议删除
复制


3 UPDATE型触发器

更改某一行时激活触发器,可能通过UPDATE语句触发

可以用OLD.columnName获取将要(BEFORE)或已经(AFTER)被修改的原数据;NEW.columnName获取将要(BEFORE)或已经(AFTER)被修改的新数据。OLD是只读的,而NEW可以使用SET进行赋值而又不再次触发触发器,从而导致循环调用。

 CREATE TABLE IF NOT EXISTS account (acct_num INT, amount DECIMAL(10,2));
 TRUNCATE TABLE account;
 -- 创建表(若表不存在)并清空
 
 INSERT INTO account VALUES(137,14.98);
 -- 插入数据
 
 delimiter $$
 CREATE TRIGGER upd_check BEFORE UPDATE ON account
 FOR EACH ROW
 BEGIN
 IF NEW.amount < 0 THEN
  SET NEW.amount = 0;
 ELSEIF NEW.amount > 100 THEN
  SET NEW.amount = 100;
 END IF;
 END$$
 delimiter ;
 -- 创建触发器,当表更新时执行BEGIN..END之间的动作(若更新后的amount<0则改为0;>100则改为100)
 -- AFTER不能对NEW进行修改,BEFORE可以对NEW进行修改;二者都不能对OLD进行修改
 
 update account set amount=-10 where acct_num=137;
 select * from account;
 -- 更新amount为-10,验证是否修改为0
 
 update account set amount=200 where acct_num=137;
 select * from account;
 -- 更新amount为200,验证是否修改为100
 
 DROP TRIGGER upd_check;
 -- 使用完建议删除
复制


4 DELETE型触发器

删除某一行时激活触发器,可能通过DELETE、REPLACE语句触发。

可以通过OLD.columnName获取将要(BEFORE)或已经(AFTER)被删除的数据,OLD是只读的。

 CREATE TABLE IF NOT EXISTS account (acct_num INT, amount DECIMAL(10,2));
 CREATE TABLE IF NOT EXISTS account_records(acct_num INT,records INT);
 TRUNCATE TABLE account;
 TRUNCATE TABLE account_records;
 -- 创建表(若表不存在)并清空
 
 INSERT INTO account VALUES(137,14.98),(141,1937.50),(97,-100.00);
 INSERT INTO account_records VALUES(137,1),(141,1),(97,1);
 -- 插入数据
 
 delimiter $$
 CREATE TRIGGER del_check AFTER DELETE ON account FOR EACH ROW
 BEGIN
  UPDATE account_records
  SET records = records - 1
  WHERE
  acct_num = OLD.acct_num ;
 END$$
 delimiter ;
 #创建触发器,当表account中删除记录时,account_records中对应的records值将减1
 
 DELETE FROM account where acct_num=137;
 select * from account_records;
 #删除数据并验证效果
 
 DROP TRIGGER del_check;
 -- 使用完建议删除
复制
文章转载自lin在路上,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论