SOQL inside a loop

Salesforce being a multi-tenant cloud platform, monitors each tenant's (organization's) process load, data usage, and so on to ensure that no tenant can cause an impact on the other tenants' processes. To achieve this, Salesforce imposes governor limits. Governor limits define the system usage allowance available to each tenant and ensures that any tenant crossing those limits is restricted to further impact the system. One such transaction level Apex limit is total number of SOQL queries issued in a single request. At present, the limit is 100 for synchronous transactions (Apex methods and triggers) and 200 for asynchronous transactions (batch Apex, future methods, and so on). So, if your code issues even one extra SOQL than the allowed limit within the code, then Salesforce will throw a governor limit exception.

For example, the following code is an Apex trigger built to automatically populate the value of an SLA field on a Contact record by taking its values from the account level SLA field:

trigger ContactCreation on Contact (before insert) { 
    for(Contact newContact : Trigger.new){ 
        Account account = [select id, SLA__c from Account where id = :newContact.Accountid]; 
        newContact.SLA__c = account.SLA__c; 
    } 
} 

Now, this code fulfills the business requirement and correctly retrieves accounts and populates the contact's SLA field. But we notice that the SOQL query is placed within the for loop. So, for each Contact record inserted, the code will perform a query.

However, when more than 100 records are inserted together, this trigger will fail. It will fail because the number of SOQL queries exceeded the limit (the SOQL limit exception).

In order to bulkify our code, we will refactor the code to ensure that only one query is executed within the trigger, irrespective of the record count, with the help of collections in Apex:

trigger ContactCreation on Contact (before insert) { 
    /* Iterate over all contacts to retrieve unique account ids */ 
    Set<Id> setAccountIds = new Set<id>(); 
    for(Contact newContact : Trigger.new){ 
        setAccountIds.add(newContact.AccountId); 
    } 
     
    /* Retrieve all related accounts and create a map of accounts */ 
    Map<id, Account> mapAccounts = new Map<id, Account>([select id, SLA__c from Account where id in :setAccountIds]); 
     
    /* Iterate over all contacts and populate SLA field */ 
    for(Contact newContact :Trigger.new){ 
        Account relatedAccount = mapAccounts.get(newContact.AccountId); 
        newContact.SLA__c = relatedAccount.SLA__c; 
    } 
} 

Note

You can also use SOQL for loops to efficiently handle large datasets within your Apex code. It provides a smart auto-chunking mechanism wherein the records are retrieved and processed in chunks, hence avoiding the maximum heap size governor limit (the current limit for the maximum heap size is 6 MB for synchronous transactions and 12 MB for asynchronous transactions).

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset