Fix DML inside a loop
Debug it · Intermediate · 15 min · Runs in your Salesforce Developer org · Apex Path
Scenario. Sales loads the quarter's Opportunities from a spreadsheet, about 180 at a time. The load fails with Too many DML statements: 151.
An Opportunity trigger creates a follow-up Task per record with insert inside the loop. It fails at 151 records. Collect first, insert once.
What you will learn
Every insert, update or delete statement counts against the limit of 150 per transaction. insert task; in a loop over 200 Opportunities is 200 statements. Salesforce stops at Too many DML statements: 151.
One statement saves up to 10,000 records, so build a list in the loop and save it once:
for (Opportunity opp : opportunities) {
followUps.add(new Task(WhatId = opp.Id));
}
insert followUps;
Gotcha. Guard the insert with isEmpty().
The task
Fix the handler so it saves all follow-up Tasks with one insert, however many Opportunities were created.
Examples:
- Opportunity
Big deal→ one Task, SubjectFollow up: Big deal, linked to the Opportunity - 3 Opportunities → 3 Tasks, each linked to its own Opportunity
- 200 Opportunities → 200 Tasks, one DML statement
Requirements:
- Build each Task in the loop with Subject
Follow up:followed by the Opportunity Name, and WhatId set to the Opportunity Id. - Add each Task to a list instead of inserting it.
- Insert the list once, after the loop, only when it is not empty.
- Keep the Task fields exactly as they are.
Starter code
public class AS_37B5DFEF8A27_FollowUpTasks {
public static void afterInsert(List<Opportunity> opportunities) {
for (Opportunity opportunity : opportunities) {
Task followUp = new Task(
Subject = 'Follow up: ' + opportunity.Name,
WhatId = opportunity.Id
);
insert followUp;
}
}
}
When it passes
Every new Opportunity gets one follow-up Task, and the trigger spends one DML statement whether it handles 1 Opportunity or 200.
You write the Apex yourself. ApexSensei runs it and tells you what passed and what did not.
‹ Fix a query inside a loop · Fix a test that checks nothing ›