The previous Best Practice talked about the importance of handling all incoming records in a bulk manner. That example showed use of a
for loop to iterate over all of the records in the Trigger.new collection. A common mistake is that queries or DML statements are placed inside a for loop. There is a governor limit that enforces a maximum number of SOQL queries. There is another that enforces a maximum number of DML statements (insert, update, delete, undelete). When these operations are placed inside a for loop, database operations are invoked once per iteration of the loop making it very easy to reach these governor limits.
Instead, move any database operations outside of
for loops. If you need to query, query once, retrieve all the necessary data in a single query, then iterate over the results. If you need to modify the data, batch up data into a list and invoke your DML once on that list of data.
Here is an example showing both a query and a DML statement inside a
for loop:trigger accountTestTrggr on Account (before insert, before update) {
//For loop to iterate through all the incoming Account records
for(Account a: Trigger.new) {
//THIS FOLLOWING QUERY IS INEFFICIENT AND DOESN'T SCALE
//Since the SOQL Query for related Contacts is within the FOR loop, if this trigger is initiated
//with more than 100 records, the trigger will exceed the trigger governor limit
//of maximum 100 SOQL Queries.
List<Contact> contacts = [select id, salutation, firstname, lastname, email
from Contact where accountId = :a.Id];
for(Contact c: contacts) {
System.debug('Contact Id[' + c.Id + '], FirstName[' + c.firstname + '],
LastName[' + c.lastname +']');
c.Description=c.salutation + ' ' + c.firstName + ' ' + c.lastname;
//THIS FOLLOWING DML STATEMENT IS INEFFICIENT AND DOESN'T SCALE
//Since the UPDATE dml operation is within the FOR loop, if this trigger is initiated
//with more than 150 records, the trigger will exceed the trigger governor limit
//of 150 DML Operations maximum.
update c;
}
}
}