function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
pdopdo 

Governor Limits on Trigger

Hi All,

I am trying to update a field (practiceid__c) on child accounts of a parent account when the parent is updated.  Unfortunately I hit the governor limits because for some reason, the trigger iterates through all my accounts and not just the ones associated with my trigger.  How do I confine the update to only the children of the account I am updating?  Here is my simple trigger:

 

trigger wfpracticeid on account (after update) {
    list<account> children = [select c.parent.practiceid__c, c.practiceid__c 
                              from account c 
                              where parentid in :trigger.new];

    for (account child :children) {
        child.practiceid__c = child.parent.practiceid__c;
    }

    update children;
}

 

Best Answer chosen by Admin (Salesforce Developers) 
pdopdo

Here is an article on how to handle recursive triggers: http://developer.force.com/cookbook/recipe/controlling-recursive-triggers

 

My code ended up looking like this:

 

Trigger

trigger wfpracticeid on account (after update) {
    set<id> parentaccid = new set<id>();
    
    list<account> accounttoupdate = new list<account>();
    
    string practiceid;
    
    if (!globalrecursivehelper.hasalreadyupdated()) {
        if (trigger.isupdate){
            for(account tempacc : trigger.new)
                if(tempacc.parentid == null && tempacc.practiceid__c != null)
                    parentaccid.add(tempacc.id);
        }
        
        
        
        for (account[] accpracticeid : [select id, practiceid__c from account where id in :parentaccid limit 1]){
            practiceid = accpracticeid[0].practiceid__c;
        }
        
        map<id,account> childmap = new map<id,account>([select parentid, id, practiceid__c from account where parentid in :parentaccid]);
    
        for (account a : [select id, practiceid__c from account where parentid != null and parentid in :parentaccid]){
            if(parentaccid.size() > 0){
                childmap.get(a.id).practiceid__c = practiceid;
            }
            accounttoupdate.add(childmap.get(a.id));
        }
        globalrecursivehelper.setalreadyupdated();
        update accounttoupdate;
    }
}

Class:

public class globalrecursivehelper {

    private static boolean alreadyupdated = false;


    public static boolean hasalreadyupdated() {
        return alreadyupdated;
    }

    
    public static void setalreadyupdated() {
        alreadyupdated = true;
    }

}

 

 

All Answers

pdopdo

Quick update to optimize the code, but I still hit the governors:

trigger wfpracticeid on account (after update) {
    list<account> children = [select c.parent.practiceid__c, c.practiceid__c 
                              from account c 
                              where parentid in :trigger.new
                              for update];

    for (account child :children) {
        if (child.practiceid__c != child.parent.practiceid__c){
            child.practiceid__c = child.parent.practiceid__c;
        }
    }

    update children;
}

 

 

SRKSRK

U write a trigger on account & update the account so it run's Recursly
Do u have diffrent record tyoe for parent & child record on account if yes then
u can try this


trigger wfpracticeid on account (after update)
 {
set<account> parentaccid = new set<account>();
for(account tempacc : trigger.new)
{
if(tempacc.recordtypeId == '<parent recordtype id>')
parentaccid.add(tempacc.id);
}
if(parentaccid.size() > 0)
{
 list<account> children = [select c.parent.practiceid__c, c.practiceid__c from account c where parentid in : parentaccid and recordtypeid = '<Child recordtype id>']; for (account child :children)
 { child.practiceid__c = child.parent.practiceid__c; } update children;
}
}
SRKSRK

If u don't have record type if have another sol to stop the Recursive trigger

Noam.dganiNoam.dgani

Hi 

 

Prior replies address valid issues in your process.

additionally, consider that a 'child' could be someone elses parent - you need to address that logicaly before

you go to the technical side

pdopdo

Hi SRK, I tried your suggestion, but am still hitting limits.  Here is my updated code:

trigger wfpracticeid on account (after update) {
    set<id> parentaccid = new set<id>();
    
    for(account tempacc : trigger.new){
        if(tempacc.this_is_a_parent_account__c == true)
            parentaccid.add(tempacc.id);
    }

    if(parentaccid.size() > 0){
        list<account> children = [select c.parent.practiceid__c, c.practiceid__c 
                                  from account c 
                                  where parentid in : parentaccid and this_is_a_parent_account__c = false];
   
        for (account child :children){
            child.practiceid__c = child.parent.practiceid__c;
        }
    
    update children;
    }
}

 

pdopdo

Okay, so I figured out that I had a trigger triggering a trigger causing the Governor Limits so I tried combining them tinto one.  I have a few roll ups and some other stuff going on, but I am still hitting the limits.  Any advice?

 

trigger wfchildrollup on account (after delete, after insert, after update) {
    
    set<id> accountids = new set<id>();
    list<account> accounttoupdate = new list<account>();
    
    for (account child : trigger.new)
        if(child.parent != null)
        accountids.add(child.parentid);
    
    if (trigger.isupdate || trigger.isdelete) {
        for (account child : trigger.old)
            accountids.add(child.parentid);
    }
    
    // get a map of the parent with the number of children
    map<id,account> parentmap = new map<id,account>([select parentid, id, count_child_accounts__c from account where id in :accountids]);

    integer childcount;
    for (account[] acc : [select id from account where parentid in :accountids]){
        childcount = acc.size();
    }
    
    integer livechildcount;
    for (account[] acclive : [select id from account where type = 'Live' and parentid in :accountids]){
        livechildcount = acclive.size();
    }
    
    date golivedate;
    for (account[] acclivedate : [select id, go_live_date__c from account where parentid in :accountids order by go_live_date__c asc limit 1]){
        golivedate = acclivedate[0].go_live_date__c;
    }
    
    string practiceid;
    for (account[] accpracticeid : [select id, practiceid__c from account where parentid in :accountids limit 1]){
        practiceid = accpracticeid[0].practiceid__c;
    }
    
    for (account a : [select id, count_child_accounts__c, count_live_child_accounts__c from account where id in :accountids]){    
    parentmap.get(a.id).count_child_accounts__c = childcount;
    parentmap.get(a.id).count_live_child_accounts__c = livechildcount;
        if (childcount > 0){
            parentmap.get(a.id).this_is_a_parent_account__c = true;
        } else {
            parentmap.get(a.id).this_is_a_parent_account__c = false;
        }
        //Need to understand validation requirements with Seth.
        //if (livechildcount > 0){
            //parentmap.get(a.id).type = 'Live';
            //parentmap.get(a.id).go_live_date__c = golivedate;
        //}
    accounttoupdate.add(parentmap.get(a.id));
    }
    update accounttoupdate;
    
    set<id> parentaccid = new set<id>();
    
    for(account tempacc : trigger.new){
        if(tempacc.this_is_a_parent_account__c == true)
            parentaccid.add(tempacc.id);
    }

    if(parentaccid.size() > 0){
        list<account> children = [select c.parent.practiceid__c, c.practiceid__c 
                                  from account c 
                                  where parentid in : parentaccid and this_is_a_parent_account__c = false];
   
        for (account child :children){
            child.practiceid__c = child.parent.practiceid__c;
        }
    
    update children;
    }
}

 

SRKSRK

 U r updating "children" which is again a account

so u need to figure out a way that u r trigger run only when parent account is update.

if parent & child both have diffrent recordtype u can put the recprdtype check o  top so it won't run for child accuounts

pdopdo

Hi SRK, I have made another attempt and resolved that issue, but now am getting too many SOQL queries.  All I want to do is query the children of the Account I am updating so I don't understand why I am getting a query limit now.

trigger wfpracticeid on account (after update) {
    set<id> parentaccid = new set<id>();
    
    list<account> accounttoupdate = new list<account>();
    
    string practiceid;
        
    if (trigger.isupdate){
        for(account tempacc : trigger.new)
            if(tempacc.parentid == null && tempacc.practiceid__c != null)
                parentaccid.add(tempacc.id);
    }
    
    for (account[] accpracticeid : [select id, practiceid__c from account where id in :parentaccid limit 1]){
        practiceid = accpracticeid[0].practiceid__c;
    }
    
    map<id,account> childmap = new map<id,account>([select parentid, id, practiceid__c from account where parentid in :parentaccid]);

    for (account a : [select id, practiceid__c from account where parentid != null and parentid in :parentaccid]){
        if(parentaccid.size() > 0){
            childmap.get(a.id).practiceid__c = practiceid;
        }
        accounttoupdate.add(childmap.get(a.id));
    }
    update accounttoupdate;
}

 

pdopdo

Here is an article on how to handle recursive triggers: http://developer.force.com/cookbook/recipe/controlling-recursive-triggers

 

My code ended up looking like this:

 

Trigger

trigger wfpracticeid on account (after update) {
    set<id> parentaccid = new set<id>();
    
    list<account> accounttoupdate = new list<account>();
    
    string practiceid;
    
    if (!globalrecursivehelper.hasalreadyupdated()) {
        if (trigger.isupdate){
            for(account tempacc : trigger.new)
                if(tempacc.parentid == null && tempacc.practiceid__c != null)
                    parentaccid.add(tempacc.id);
        }
        
        
        
        for (account[] accpracticeid : [select id, practiceid__c from account where id in :parentaccid limit 1]){
            practiceid = accpracticeid[0].practiceid__c;
        }
        
        map<id,account> childmap = new map<id,account>([select parentid, id, practiceid__c from account where parentid in :parentaccid]);
    
        for (account a : [select id, practiceid__c from account where parentid != null and parentid in :parentaccid]){
            if(parentaccid.size() > 0){
                childmap.get(a.id).practiceid__c = practiceid;
            }
            accounttoupdate.add(childmap.get(a.id));
        }
        globalrecursivehelper.setalreadyupdated();
        update accounttoupdate;
    }
}

Class:

public class globalrecursivehelper {

    private static boolean alreadyupdated = false;


    public static boolean hasalreadyupdated() {
        return alreadyupdated;
    }

    
    public static void setalreadyupdated() {
        alreadyupdated = true;
    }

}

 

 

This was selected as the best answer