
We use three kinds of cookies on our websites: required, functional, and advertising. You can choose whether functional and advertising cookies apply. Click on the different cookie categories to find out more about each category and to change the default settings.
Privacy Statement
Required cookies are necessary for basic website functionality. Some examples include: session cookies needed to transmit the website, authentication cookies, and security cookies.
Functional cookies enhance functions, performance, and services on the website. Some examples include: cookies used to analyze site traffic, cookies used for market research, and cookies used to display advertising that is not directed to a particular individual.
Advertising cookies track activity across websites in order to understand a viewer’s interests, and direct them specific marketing. Some examples include: cookies used for remarketing, or interest-based advertising.
This article explains how Trigger.old and Trigger.new context variables work in Salesforce Apex triggers, and how their values differ before and after record changes occur. Trigger.old and Trigger.new are Apex Trigger Context Variables — special collections that provide access to the records that caused the trigger to fire.
Trigger.new contains all the records that were inserted in insert or update triggers, representing the new version of the records after the trigger event. Trigger.old provides the old version of sObjects before they were updated in update triggers, or a list of deleted sObjects in delete triggers.
Triggers can fire when one record is inserted, or when many records are inserted in bulk via the API or Apex. Therefore, context variables such as Trigger.new can contain one record or multiple records. You can iterate over Trigger.new to get each individual sObject.
When a field value is updated to a certain value, use Trigger.old and Trigger.new to compare the older and new version values of field values on a record and perform the required business logic accordingly.
Consider the following setup: You have a workflow rule on Account object creation that updates a field such as the Description field. You then have a trigger that fires after the workflow update and iterates over Trigger.old, expecting to get the Description field that was modified by the workflow. In this case, you will get a NullPointerException.
The reason for the NullPointerException comes down to understanding what values these two context variables hold at different points in the transaction.
Trigger.old values represent the state of records before the CURRENT transaction (the user's action that initiated the trigger). Trigger.new represents the state of records after the current transaction's DML completes.
In the example above, since it is an insert scenario, Trigger.old will NOT hold the Description field updated by the workflow rule — because the workflow fired as part of the same insert transaction and Trigger.old captures the pre-transaction state.
You'll have to query the database after the workflow field update fires In order to obtain that same field.
For example:
List<Account> accts = [Select Id, FieldUpdatedByWorkflow__c from Account where Id in : Trigger.old];
See the sample trigger below.
Note: Create a workflow field update on Account objects creation to see the results in the debug log.
trigger testTrigger on Account (before update, after update, before insert, after insert)
{
if (Trigger.isBefore) {
System.debug('********Trigger values***********');
System.debug('***SFDC: Trigger.old is: ' + Trigger.old);
System.debug('***SFDC: Trigger.new is: ' + Trigger.new);
}
if (Trigger.isAfter) {
System.debug('********Trigger values***********');
System.debug('***SFDC: Trigger.old is: ' + Trigger.old);
System.debug('***SFDC: Trigger.new is: ' + Trigger.new);
}
}
However, Trigger.new WILL contain the Description field updated by the workflow, along with any other fields populated at object creation.
To access the workflow-updated field in Trigger.old, you must perform an explicit SOQL query after the workflow update fires. For example, query the Account object by the record IDs in Trigger.old: SELECT Id, FieldUpdatedByWorkflow__c FROM Account WHERE Id IN :Trigger.old. This retrieves the most current version of those records from the database, including any workflow-updated fields.
The sample trigger provided in the additional resources logs both Trigger.old and Trigger.new during before and after insert and update events on Account. Running this trigger with a workflow field update on Account creation allows you to observe in the debug log how Trigger.new reflects the workflow update while Trigger.old does not during the insert event.
000384697