在Apex循环中查询子记录时,如何规避SOQL查询限制错误?
解决Apex中SOQL查询超限问题
问题根源
你的代码在for (Account acc : accounts)循环内执行SOQL查询,每处理一个Account就发起一次Contact查询。当传入的Account数量超过100时,就会触发Salesforce的单次事务最大100次SOQL查询限制;同时循环内的update contacts会导致多次DML操作,也可能触发单次事务最多150次的DML限制。
优化方案
采用批量查询+批量更新的方式,把SOQL和DML操作都从循环中抽出来,仅执行一次:
public with sharing class AccountProcessor { public void processAccounts(List<Account> accounts) { // 收集所有待处理Account的ID Set<Id> accountIds = new Set<Id>(); for (Account acc : accounts) { accountIds.add(acc.Id); } // 批量查询所有关联的Contact,仅一次SOQL List<Contact> contacts = [SELECT Id, Email, AccountId FROM Contact WHERE AccountId IN :accountIds]; // 用Map建立Account ID到对应Contact列表的映射,快速匹配关联记录 Map<Id, List<Contact>> accountToContactsMap = new Map<Id, List<Contact>>(); for (Contact con : contacts) { if (!accountToContactsMap.containsKey(con.AccountId)) { accountToContactsMap.put(con.AccountId, new List<Contact>()); } accountToContactsMap.get(con.AccountId).add(con); } // 统一收集需要更新的Contact List<Contact> contactsToUpdate = new List<Contact>(); for (Account acc : accounts) { List<Contact> relatedContacts = accountToContactsMap.get(acc.Id); if (relatedContacts != null && !relatedContacts.isEmpty()) { for (Contact con : relatedContacts) { con.Description = 'Processed'; contactsToUpdate.add(con); } } } // 批量执行更新,仅一次DML if (!contactsToUpdate.isEmpty()) { update contactsToUpdate; } } }
优化点说明
- 消除循环内SOQL:通过
IN :accountIds一次性拉取所有关联Contact,将SOQL查询次数从N次(N为Account数量)降到1次,彻底规避SOQL超限问题。 - 合并DML操作:把所有需要更新的Contact汇总后统一执行
update,减少DML调用次数,避免触发DML限制。 - Map提升匹配效率:用Map存储Account与Contact的关联关系,避免嵌套循环的低效遍历,提升代码执行速度。
额外建议
如果处理的记录量极大(比如超过1万条),建议结合Batch Apex拆分处理,进一步规避单事务的记录数量限制。
内容的提问来源于stack exchange,提问作者Prasanna Kuracha
相关产品推荐
相关产品推荐

