Apex Tip: How to make a DML operation in a trigger After insert/update

Many times I’ve faced requirements to write a field in a trigger after the record is inserted or update. So, naturally I’ve tried something like this:

But there the record is read only and if you try to change a field value this exception will be fired:

execution of AfterInsert caused by: System.FinalException: Record is read-only

The workaround is quite simple. The object contained by the global trigger.new is read-only, but you can create a new object referring the same ID and change the value that you need.

In addition you have to avoid the recursion since you are changing the record the trigger will be fired again. To avoid that you have to use a static flag which says that the trigger has been already executed during the current executing context.

So, the final code should be like this:

Enjoy :)

13 thoughts on “Apex Tip: How to make a DML operation in a trigger After insert/update

  1. Vaibhav

    Hi Martin,

    I tried to apply the same logic with one of the custom object – Merchandise and tried to update one of the text field but failing to make the update to record from UI.

    Below is the basic code I tried for in AfterUpdate scenario and without any recursive checks :

    trigger checkTheStaticCounter on Merchandise__c (after Update) {

    if(trigger.new != null && trigger.new.size() > 0){
    List merchList = new List();
    for(Merchandise__c merchObj : trigger.new){
    Merchandise__c newObj = new Merchandise__c(Id = merchObj.id);
    merchObj.Sample_Text_Field__c = ‘Update is happening in same context of afterUpdate trigger’;
    merchList.add(merchObj);
    }
    update merchList;
    }

    }

    I am still facing the read only error. Any suggestions where I am going wrong.

    Reply
  2. Jim

    What does this mean?

    aux.Name = a.Id + ‘Value forced to be set after by an extrange req’;

    I have tried the following in my code and nothing updates:

    trying to set t.Dependency__c = newDependency

    aux.id = newDependency
    aux.Name = t.id + newDependency

    Reply
  3. Anshuman

    I am using the same code as you have provieded, however a Text Area is not getting updated with the message. I am pasting code below

    trigger changeValueAfterAccountUpdate on Account (after update) {

    Account[] accounts = new Account[]{};
    for (Account a: Trigger.new) {
    Account aux = new Account(Id = a.Id);
    aux.StatisticsMessage__c = aux.Id + ‘Value forced to be set after by an extrange req’;
    }

    update accounts;
    }

    Reply
  4. Beau Anderson

    The example you give removes the read only problem BUT something doesn´t seem right.

    You have 3 entities
    1. accounts
    2. a
    3. aux

    You assign trigger new to a then a to aux and finally update accounts. If you debug the code you might see that accounts is empty so nothing gets updated. I haven´t figured out how to make it work but seems like your code is close but missing the step to assign the new values to the object that gets updated

    Reply
    1. Beau Anderson

      Maybe this will help

      accounts needs to be a list not an object. Inside the for loop you need to add aux to the accounts list

      list accounts = new list ();
      for (Account a: Trigger.new) {
      //here the magic by creating a new instance using the same id
      Account aux = new Account(Id = a.Id);
      aux.Name = a.Id + ‘Value forced to be set after by an extrange req’;
      accounts.add(aux);
      }
      //then update the new instance list.
      update accounts;

      Reply
      1. Beau Anderson

        the list declaracion doesn´t save well in this site. updating the line so that the type is visible
        list ” lCuentasNueva = new list ”();

        Reply
        1. Beau Anderson

          Sorry it´s not working so will try to explain. When you declare a list you need to put the object inside less then symbol and greater than symbol. When I put the les than and greater than symbol into the comment area on this site it doesn´t render so will try typing it.

          list “less than symbol” Account “greater than symbol” accounts = new list “less than symbol” Account “greater than symbol”();

          Reply
  5. Irene

    I’m getting an error ‘Loop variable must of type SObject’. I tested copying and pasting the exact code you gave as I thought I might have made an error in mine, but am also getting this error on both my code and yours. The error points to the ‘for’ loop.

    I created the trigger, then the class. Help?

    Reply
  6. Prashant

    I’ve tried the exact final code provided and getting the error: unexpected token: public at line 8. Am I missing something here. Please help.

    Reply
  7. MonaWilsonb

    I see your blog needs some unique & fresh articles.
    Writing manually is time consuming, but there is solution for this.

    Just search for – Masquro’s strategies

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">