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";

posted on 2018-06-01 20:42  疯狂的妞妞  阅读(184)  评论(0编辑  收藏  举报

导航