Trigger.new vs Trigger.old — 正确理解 Apex 触发器

发布: (2026年2月6日 GMT+8 23:06)
5 min read
原文: Dev.to

Source: Dev.to

(请提供需要翻译的正文内容,我才能为您完成简体中文的翻译。)

介绍

在学习 Apex 触发器时,关键是要弄清何时使用 Trigger.newTrigger.old

  • Trigger.new – Salesforce 正在尝试保存的当前数据。
  • Trigger.old – 变更之前已经存在的数据。

牢记这一区别,大多数使用场景就会变得合乎逻辑。

Trigger.new

它代表什么

Trigger.new 包含 Salesforce 正在尝试插入或更新的当前或即将到来的值。

常见用例

  • 验证
  • 设置或修改字段值
  • 读取已更新的值
  • 基于新数据创建关联记录

在以下上下文中可用

场景是否可用
Insert(插入)
Update(更新)
Undelete(恢复)

Undelete:当记录从回收站恢复时会触发此上下文,Trigger.new 包含被恢复的记录值。

示例:验证

for (Contact con : Trigger.new) {
    if (con.Email == null) {
        con.Email.addError('Email is required');
    }
}

该验证能够工作是因为 Trigger.new 代表了当时正在保存的数据。

Trigger.old

它代表什么

Trigger.old 是记录在更改 之前 的快照。

常见用例

  • 检测字段变化
  • 基于先前值的条件逻辑
  • 防止重复操作

可用的上下文

场景是否可用
Update
Delete

示例:检测变化

for (Opportunity newOpp : Trigger.new) {
    Opportunity oldOpp = Trigger.oldMap.get(newOpp.Id);
    if (newOpp.StageName != oldOpp.StageName) {
        // Stage has changed
    }
}

Trigger.old 提供用于比较的先前状态。

示例:检测有意义的更新

for (Opportunity newOpp : Trigger.new) {
    Opportunity oldOpp = Trigger.oldMap.get(newOpp.Id);
    if (newOpp.StageName == 'Closed Won' &&
        oldOpp.StageName != 'Closed Won') {
        // Stage just changed to Closed Won
    }
}

提示

  • Trigger.oldMapTrigger.newMap 可快速通过 Id 访问记录(Id → Record)。
  • 在批量操作中比较旧值和新值时,使用映射比循环更佳。
  • 只要你的逻辑依赖于检测变化(而不仅是当前值),就需要同时使用 Trigger.newTrigger.old

Source:

基于上下文的决策表

需求用途
验证输入Trigger.new
修改字段Trigger.new
比较新旧记录Trigger.new + Trigger.old
删除前清理Trigger.old
阻止记录保存Trigger.new.addError()

触发器类型

触发器类型操作说明
Before修改 Trigger.new
After读取 Trigger.new,并与 Trigger.old 比较

重要:after 触发器中不能使用 Trigger.new 修改记录,因为记录已经提交到数据库。此时 Trigger.new 为只读。任何进一步的更改都需要单独的 DML 操作。

示例:在 after 触发器中使用 DML 更新

List<Account> accsToUpdate = new List<Account>();
for (Account acc : Trigger.new) {
    accsToUpdate.add(new Account(
        Id = acc.Id,
        Name = 'Updated Name'
    ));
}
update accsToUpdate;

触发器上下文概览

上下文可用数据目的
插入前Trigger.new记录尚不存在;在保存前修改字段
更新前Trigger.new + Trigger.old对比旧值和新值;在保存前修改字段
更新后Trigger.new + Trigger.old记录已保存;只读,检测变化
删除前Trigger.old记录即将被删除;执行清理逻辑
删除后Trigger.old记录已删除;只读,用于审计或相关逻辑

可视化数据的时间线可以自然地帮助选择正确的上下文。与其记忆规则,不如问自己:

“我是在处理 new 数据、old 数据,还是它们之间的 变化?”

一旦回答明确,合适的上下文(Trigger.newTrigger.old 或两者)就显而易见。

最佳实践

  • Bulkify 你的触发器 – 循环遍历集合,如 Trigger.new,而不是单条记录,以避免治理限制。
  • 使用 Trigger.newMapTrigger.oldMap 通过 Id 进行高效查找,而不是使用嵌套循环。
Back to Blog

相关文章

阅读更多 »