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
Sparky JaneSparky Jane 

How to write query outside the for loop in triggers?

trigger fieldupdate on Contact (before insert, before update) {
     for(Contact c : Trigger.new){
    Account val = [SELECT Acc_Cost__c from Account where Id=:c.AccountId];
    val.Acc_Cost__c +=c.Cost__c;
    upsert val;
    }
Best Answer chosen by Sparky Jane
Grazitti TeamGrazitti Team
Hi RVL,

Below is the modified code .

List<Id> conIds = new List<Id>();
     for(Contact c : Trigger.new){
    conIds.add(c.Id);
     }
List<Account>  val = [SELECT Acc_Cost__c from Account where Id in :conIds];
   
//now the Query is  outside the for loop , so you can do the further processing

    }


and there is governor limit on Dml as well . so never fire a dml inside for loop.

let us know if you have any question .
please don't Forget to Mark this as your best answer if it works fine for you

Regards,
Grazitti Team
Web: www.grazitti.com


All Answers

SravsSravs
have look at this. 

https://developer.salesforce.com/forums/#!/feedtype=SINGLE_QUESTION_DETAIL&dc=Developer_Forums&criteria=ALLQUESTIONS&id=906F0000000AfETIA0

Regards,
Sravs
Grazitti TeamGrazitti Team
Hi RVL,

Below is the modified code .

List<Id> conIds = new List<Id>();
     for(Contact c : Trigger.new){
    conIds.add(c.Id);
     }
List<Account>  val = [SELECT Acc_Cost__c from Account where Id in :conIds];
   
//now the Query is  outside the for loop , so you can do the further processing

    }


and there is governor limit on Dml as well . so never fire a dml inside for loop.

let us know if you have any question .
please don't Forget to Mark this as your best answer if it works fine for you

Regards,
Grazitti Team
Web: www.grazitti.com


This was selected as the best answer
Gigi.OchoaGigi.Ochoa
Are you trying to do a "rollup summary" of Acc_Cost__c field on Contacts to Account.  Unfortunately, you cannot just create a rollup summary field on the Account object, since Account/Contacts are technically not master/detail to each other.

Give this a try (please use after insert, after update on your trigger)
// Use a set to get your account Ids
Set<Id> acctIds = new List<Id>();

for(Contact c: trigger.new){
    if(c.AccountId !=null) acctIds.add(c.AccountId);
}

// create Map of Account Id to Acc_Cost__c Sum
Map<Id, Double> accToAccCostMap = new Map<Id, Double>();
AggregateResult[] groupedResults  = [SELECT SUM(Acc_Cost__c), AccountId FROM Contact WHERE AccountId IN :acctIds GROUP BY AccountId];
for (AggregateResult ar : groupedResults)  {
    accToAccCostMap.put(ar.get('AccountId'), (Double)ar.get('expr0'));
}

// create a map of your accounts
List<Account> accounts= [SELECT Acc_Cost__c from Account WHERE Id IN :acctIds];

for(Account a:accounts){
    if(accToAccCostMap.containsKey(a.Id))  a.Acc_Cost__c = accToAccCostMap.get(a.Id);
}

update accounts;

Also, this is a good reference on how to bulkify your code, avoid DML inside your loop and other Apex Best Practices.
Gigi.OchoaGigi.Ochoa
Oops. here is the link for Apex Best Practices.
https://developer.salesforce.com/page/Apex_Code_Best_Practices