Compare old and new values in trigger salesforce

In validation rules we have something called ischanged, do we have similar function in triggers? Well, we don't have exact same function but we have trigger context variables that can be used to implement similar functionality. So, how do we compare values in trigger. How do we check if a field value is changed or not. To see if the value is changed or not we would need fields prior value in apex trigger. To compare the old value and new value in trigger we can use trigger new map and trigger old map.

Basically, to compare old field value of record with the new value in trigger we need to access trigger.oldmap and trigger.newmap. Salesforce provides trigger.oldmap where in all the old records are stored in map with keyset as their id's. We can compare the old values with new values as in the below example. Lets understand how we can implement such a data validation by getting old value in triggers.

Understanding trigger.oldmap and trigger.newmap in salesforce:
Salesforce provides trigger context variables which allows to access run time context data in trigger. There are around 12 trigger context variables that help in identifying record data in curent context, the context if the triger (like whether the current execution is insert type or update type, whether).

What is trigger.Newmap
Trigger.newmapis bascially a collection of type map. Its keyset is Id and values are the new version of sobject record. For example if a lead record is being modified the the trigger.newmap in lead trigger would be map<id,lead>.

trigger updatetrigger on lead(before update){
   for(lead lea : trigger.new){
        system.debug('lea will be equal to' : trigger.newmap.get(lea.Id));
    }
}

Trigger.newmap is available in before update, after update, after insert and before undelete. Remember its not available during before insert, it is only logical.

What is trigger.oldmap 
Trigger.oldmap is also a collection of type map. Its keyset is Id and values are the prior or old version of sobject record in current context. Here also if a lead record is being modified then the trigger.oldmap in lead trigger would be map<id,lead>. Trigger.oldmap is available in before update, after update, before delete and after delete. It is not available in insert trigger, here again its so logical. How can you have old version of record when it is just being inserted.

For example say a field value on lead record is modified to a new value. lets see a tigger.newmap and trigger.oldmap example to see what we get.

Ex: A email field on lead is changed from "mytest@xyz.com" to "newvalue@xyz.com" then if you access trigger.oldmap will have lead record that will have email as "mytest@xyz.com"  and the trigger.newmap will have lead record with a email address as "newvalue@xyz.com"

Lets summarize the difference between trigger.oldmap and trigger.newmap.
trigger.oldmap gives a map of id and records that will have older version of record data where as trigger.newmap gives a map of id and newer version of records data. Second point of difference is about that the triggers where it is available. trigger.Oldmap avaible only in update and delete triggers where as trigger.newmap available after insert and after undelete trigger.

Lets build a salesforce trigger to check if field value has changed or not. In Below example, the trigger compares the account number old value with the new value. That is, trigger checks if the account number was changed.

If the account number is changed the trigger assigns the type field value "prospect" else it assigns it a value "Other" 

trigger Compare_OldandNewvalues on Account (before update) {


   for (Account acc: Trigger.new) {

        Account oldAccount = Trigger.oldMap.get(acc.ID);
        if(acc.AccountNumber != oldAccount.AccountNumber) {
           System.debug('--*Account Number is changed*--');
           System.debug('**Old Account Number :'+oldAccount.AccountNumber);
           System.debug('**New Account Number :'+acc.AccountNumber);
           acc.Type = 'Prospect';
        }
        else{
            System.debug('--**Account Number has not been Updated**--');
            acc.Type = 'Other';  
        }
    }
}

Lets see what other context variables we have and how we can make use of them. 

Trigger.IsInsert : This context variables returns true is the current execution of trigger is due to insert of a new record
Trigger.Isupdate : A context variable used to identify if the current execution is due to update of a record
trigger.Isdelete: This context variable signifies trigger execution is due to delete operation
trigger.undelete : This context variable returns true if the execution of trigger was due to undelete operation.
trigger.isbefore: this context variable is set to true if the trigger is fired before a record is saved.
trigger.isafter : this context variable returns true if the trigger was fired after the record was saved
And now the other most important ones:
trigger.new: trigger.new returns the new version of record in a list. So its a list collection unlike trigger.newmap which is a map.
trigger.old : this is an old version of records and also a list type collection unlike trigger.oldmap which returns map

Difference between trigger.old and trigger.new 
1. trigger.old returns a list with old version of records where as trigger.new returns a new version of records in a list
2. trigger.new is available in insert triggers, update triggers and undelete triggers wile trigger.old are available in update and delete triggers.
3. Records can be modified and committed by inly changing the values in trigger.new, for example below trigger will change the leadsource to web on all the leads modified,

trigger changevalue on lead (before update){

  for(lead lea : trigger.new){
      lea.leadsource = 'web';
  }  
}

4 comments:

  1. Thank you so much for this piece of code. It really helped me ALOT.

    ReplyDelete
  2. one question on this. When i change an attribute, i don't have to make a DML call, becuase it will be picked up by the update who caused the trigger? Thanks!

    ReplyDelete
  3. Hi guys,
    I have one question please quid me.

    trigger Compare_OldandNewvalues on Account (before insert) //how can i use.
    I am fetching all the account Number from Account Using SOQL.
    List oldAccount =[select AccountNumber from Account];
    but how to compare single account with List of account.

    ReplyDelete