oracle - 触发器
介绍触发器之前,先讲道理将你们劝退。
在你的整个职业生涯中,包括面试,大概率遇不到触发器,没必要花费太多时间学习。
对业务的影响
一般在项目中,会直接禁用触发器,因为一个业务流,无法预知会经历哪些触发器。
举个例子:
业务上需要保存一份数据,值为 3,经过触发器的计算,数值最终变成了 5。
项目初期可能是对的,运行很久之后,因为业务调整,逻辑发生变化。
这时候就会发现,Java 程序执行过程中,所有日志都显示正常,只有结果不对。
如果不是对项目十分了解,几乎不会有人想到是触发器的问题。
JDBC 注意事项
想要使用触发器,需要项目一开始启用,允许 JDBC 一次执行多个 SQL,否则会出现下列这种报错,
需要在 JDBC 的 url 中添加 allowMultiQueries=true
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax;
check the manual that corresponds to your MySQL server version for the right syntax to use
near 'CREATE TRIGGER upd_check BEFORE UPDATE ON account
基本结构
-- 清除已有的触发器
DROP TRIGGER my_trigger;
-- 创建一个在插入数据时触发的触发器
CREATE TRIGGER my_trigger
BEFORE UPDATE ON my_table -- 在什么时候触发:在 my_table 表上插入数据之前触发
FOR EACH ROW -- 对每一行数据都触发,如果没有这一选项,则只对整个表执行一次
WHEN (OLD.age > 17) -- 设置数据过滤条件:年龄大于 17
BEGIN
-- 触发器逻辑处理代码
-- 可以在此处执行一些额外的操作,例如:数据验证、日志存储等
-- 使用 NEW 关键字引用将要修改之后的数据
-- 使用 OLD 关键字引用将要修改之前的数据
-- 示例:将插入数据的创建时间设置为当前时间
:NEW.create_time := SYSDATE;
END;
一般照着这个代码复制即可,格式上需要变动的是这一行:
BEFORE UPDATE ON my_table
触发时机:指明触发器何时执行,该值可取:
- before:数据更新之前触发;
- after: 数据更新之后触发。
触发事件,指明哪些数据库动作会触发此触发器,有下面这些选项:
- insert:新增时触发;
- update:修改时触发;
- delete:删除时触发。
样例
-- 在触发器中阻止非法操作
-- 案例:如果今天不是周六或者周天,不允许变更数据
CREATE OR REPLACE TRIGGER "ABCDE"
BEFORE INSERT OR DELETE OR UPDATE
ON TABLE1
FOR EACH ROW
BEGIN
IF(TO_CHAR(SYSDATE,'DAY') IN ('星期六','星期天')) THEN
-- 抛出异常
RAISE_APPLICATION_ERROR(-20001,'不是上班时间,不允许修改');
END IF;
END;
-- 操作新值和旧值
-- 案例:触发修改的时候,要在原先的值基础上,加上新的值
CREATE OR REPLACE TRIGGER "ABCDE"
BEFORE UPDATE
ON TABLE1
FOR EACH ROW
DECLARE -- 注意声明变量
BEGIN
-- 新的 age = 新的 age + 旧的 age
:NEW.T_AGE := :NEW.T_AGE + :OLD.T_AGE;
END;
-- 增加过滤条件
CREATE OR REPLACE TRIGGER "ABCDE"
BEFORE DELETE
ON TABLE1
FOR EACH ROW
WHEN(OLD.T_AGE < 17) -- 当 age 小于 17 时
BEGIN
-- 抛出异常
RAISE_APPLICATION_ERROR(-20001,'他还是个孩子');
END;
-- 删除触发器
drop trigger "ABCDE";
疯狂的妞妞 :每一天,做什么都好,不要什么都不做!