从头开始学MySQL-------触发器

版权声明:欢迎转载大宇的博客,转载请注明出处: https://blog.csdn.net/yanluandai1985/article/details/83749433

12.1.1  创建触发器

        触发器是由事件触发的操作,这些事件包括INSERT、UPDATE、DELETE事件。触发器是一种特殊的存储过程,它预定义了一些SQL,不用CALL来调用。当指定的事件发生的时候,触发器就会自动执行。

触发器语法:

CREATE TRIGGER trigger_name  trigger_time  trigger_type  ON  table_name 

FOR EACH ROW trigger_stmt   

trigger_name  是触发器的名字

trigger_time 取值为BEFORE和AFTER,表示触发时机。

trigger_type 指触发事件,包括INSERT  UPDATE  DELETE

trigger_stmt 可以编写存储过程,比如 SET @result = NEW.字段。    NEW代表刚才更新或者插入的记录。

        触发器用来满足一些复杂的业务需要,比如根据客户当前的账户状态,判断是否允许插入新的订单。

-- 下面的触发器定义的意思是:
-- 在table_name表执行UPDATE操作之前,先往t_operation表中插入一条记录,再执行更新的SQL
CREATE TRIGGER trigger_name BEFORE UPDATE ON table_name
FOR EACH ROW
BEGIN
     INSERT INTO t_operation(..) VALUES(..);
END

        首先准备3张表,存钱记录表t_take_in、取钱记录表t_take_out与银行余额表t_bank。

        现在需求:假设银行余额现在有500,即t_bank表中有一条记录,金额属性为500。如果往t_take_in表中插入一条记录,意味着存了一笔钱。如果往取钱记录表t_take_out表中插入一条记录,意味着取了一笔钱。例如,往存钱记录表t_take_in插入一条金额为100的记录,即又存了100,那么银行余额表t_bank的金额属性应该为600。再往取钱记录表t_take_out中插入一条金额为200的记录,意味着取了200,那么银行余额表t_bank的金额属性应该剩余400。

DROP TABLE IF EXISTS t_take_in;

CREATE TABLE t_take_in  -- 存钱记录表
(
   id INT(11) PRIMARY KEY AUTO_INCREMENT,
  money DECIMAL(5,2),  -- 存入金额
  inDate DATETIME DEFAULT NOW() -- 存入时间
);

DROP TABLE IF EXISTS t_take_out;

CREATE TABLE t_take_out  -- 取钱记录表
(
   id INT(11) PRIMARY KEY AUTO_INCREMENT,
  money DECIMAL(5,2),  -- 支出金额
  outDate DATETIME DEFAULT NOW()  -- 支出时间
);

 

 

        再创建一个账户表。我的打算是这样的,假设账户表中已经有了一定的钱。向“存钱记录表t_take_in”中存放钱,将会触发余额表的触发器,让它更新"银行余额表t_bank"。同样,在"取钱记录表t_take_out"中插入数据,意思是当前用户取出了一笔钱,那么也用触发器,同步更新"银行余额表t_bank"。

DROP TABLE IF EXISTS t_bank;

CREATE TABLE t_bank
(
   money  DECIMAL(5,2)
);

INSERT INTO t_bank(money) VALUES(500);

  

        下面开始创建触发器。

DELIMITER //

CREATE TRIGGER addMoney AFTER INSERT ON t_take_in -- 为存钱表加入AFTER INSERT触发器
FOR EACH ROW
  BEGIN
     UPDATE t_bank SET MONEY = MONEY + NEW.money; -- 存钱表存钱后触发更新,NEW代表刚才更新或者插入的记录。
  END //

DELIMITER ;

  

DELIMITER //
 
CREATE TRIGGER useMoney AFTER INSERT ON t_take_out -- 在取钱记录表上创建AFTER INSERT触发器
FOR EACH ROW                                       -- 即当t_take_out出现INSERT语句的时候,执行下面的SQL
BEGIN                                              
    UPDATE t_bank SET MONEY = MONEY - NEW.money;   -- NEW代表刚才更新或者插入的记录。
END //
 
DELIMITER ;

-- 现在向存钱表里面存钱
INSERT INTO t_take_in(money) VALUES(100);

        查看各个表的情况。

        存钱记录表t_take_in表里面多了刚才插入的记录。

  

        最关键的"账户表t_bank"的情况,我们来看看。从500变成了600,说明触发器中的SQL执行了。

  

        再来测试一下向"取钱记录表t_take_out"中插入数据,即新增一笔取款记录。

-- 现在向取钱表里面取钱,取200块,账户表预期剩余600-200 = 400元
INSERT INTO t_take_out(money) VALUES(200);

         取钱记录表t_take_out表里应该新增一条记录。新增取款200块。

  

         账户表t_bank应该预期为400。

         与预期一致,说明触发器设置成功。

拨云见日

        原来触发器也不是什么神秘的东西,它是一种特殊的存储过程,它预定义了一些SQL语句。当其它表发生增删改事件的时候,它就会被触发,执行预定义的SQL。

        从设计模式的角度来看待,它其实就是一种观察者设计模式。从Java的角度来看待,它就是一个监听器。触发器触发后将会执行定义好的SQL语句。

12.1.2  查看触发器

        所有的触发器都存放在information_schema数据库中的triggers表中。

SELECT * FROM information_schema.`TRIGGERS` WHERE TRIGGER_NAME LIKE '%Money%'

        第二种方法就是最常用的方法:SHOW TRIGGERS;

SHOW TRIGGERS;

12.1.3  删除触发器 

DROP TRIGGER IF EXISTS useMoney;

-- 补充删除视图的方法

DROP VIEW IF EXISTS view_name;

12.1.4  专家解惑

        惑而不从师其为惑也终不解矣。

能不能创建两个相同事件的触发器?

        比如能否在同一张表上创建两个 BEFORE INSERT 触发器?答案是不可以。此时,只可以在这张表上创建其它的触发器,比如 AFTER INSERT,BEFORE UPDATE。

        结论:相同事件只能创建一个触发器。

表结构发生更改,触发器会自动删除吗?

        表结构发生更改,不会自动删除触发器,除非删除了这张表,触发器会自动被删除。

        如果因为需求的变化,旧的触发器没有被及时手动删除的话,旧的触发器将会照常工作,可能会影响数据完整性,因此需要手动删除。DROP TRIGGER trigger_name;

猜你喜欢

转载自blog.csdn.net/yanluandai1985/article/details/83749433