You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何检测触发器触发的DML操作类型(INSERT/UPDATE/DELETE)以记录操作日志?

核心疑问解答

关于序列的配置

  • 完全不需要为每类DML单独创建序列。你为LOG表ID配置的专属自增序列已经可以复用,和日志对应的DML操作类型没有耦合,单条序列就能满足所有操作类型的日志主键生成需求。

关于触发器的实现方案

你完全不需要拆分多个触发器,直接创建一个同时绑定INSERT/UPDATE/DELETE三种操作的AFTER行级触发器即可(注意必须指定为行级触发器,否则一条DML修改多行数据时只会触发一次,无法逐行记录变更)。

操作类型的判断逻辑

所有主流数据库的触发器都内置了操作判断变量,不需要额外自定义判断逻辑:

  • Oracle:提供INSERTING、UPDATING、DELETING三个布尔内置变量,直接判断即可
  • PostgreSQL:提供TG_OP内置变量,返回值直接就是'INSERT'/'UPDATE'/'DELETE'的字符串
  • MySQL:同样支持INSERTING、UPDATING、DELETING三个判断分支

原有触发器的问题修正

你原本写的SELECT record FROM TableA逻辑存在两处核心错误:

  • DELETE操作触发时,被删除的行已经从TableA中移除,全表查询根本无法获取被删的数据
  • 行级触发器必须通过触发器临时变量取当前变更行的数据:INSERT/UPDATE取NEW临时变量的行值,DELETE取OLD临时变量的行值,否则会错误地把全表数据写入日志

修正后的触发器示例(以Oracle语法为例)

CREATE OR REPLACE TRIGGER trg_tablea_dml_log
AFTER INSERT OR UPDATE OR DELETE ON TableA
FOR EACH ROW -- 必须指定为行级触发,否则只会在语句执行完成后触发一次
AS
  v_event VARCHAR2(10);
  v_record VARCHAR2(1000); -- 类型按你实际LOG表record字段调整
BEGIN
  -- 判断当前触发的操作类型
  IF INSERTING THEN
    v_event := 'INSERT';
    v_record := :NEW.record; -- 取新插入行的record值
  ELSIF UPDATING THEN
    v_event := 'UPDATE';
    v_record := :NEW.record; -- 取变更后行的record值
  ELSIF DELETING THEN
    v_event := 'DELETE';
    v_record := :OLD.record; -- 取被删除行的record值
  END IF;

  -- 写入日志表,ID、TS字段无需手动赋值,序列和默认值会自动填充
  INSERT INTO LOG (event, record)
  VALUES (v_event, v_record);
END;

注意:不同数据库的触发器语法细节有差异,比如PostgreSQL不需要手动判断分支,直接用TG_OP给event赋值即可;MySQL的临时变量前缀为NEW./OLD.,不需要冒号,但整体逻辑完全一致。

内容的提问来源于stack exchange,提问作者Tony

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.29 17:06:01