+ Start a Discussion
Gita BorovskyGita Borovsky 

Sudden "Too many SOQL queries" Error

Hi All,

This trigger has been running just fine with no no errors, then yesterday starting throwing back "UpdateLeadOwner: System.LimitException: Too many SOQL queries: 101"

Here's the code:

trigger UpdateLeadOwner on Lead (before insert,before update) {
    for (Lead leadInLoop : Trigger.new) {
   
if (leadInLoop.LeadSource != 'Contact Us' && leadInLoop.LeadSource != 'Reprint') {
    // Retrieve owner from Account record based on email domain name
    list <Account> acct = [Select OwnerId from Account WHERE Domain__c = :leadInLoop.Domain__c AND Owner.UserRoleId != '00E50000000t0Bf' Limit 2];
        if (acct.size() == 1) {

    System.debug('account owner id is: ' + acct[0].OwnerId);
    leadInLoop.OwnerId=acct[0].OwnerId;
        }
    }
}

Any idea how to track down what changed so I can fix?  Thanks!
James LoghryJames Loghry
Your trigger is not "bulkified" and your querying in a for loop.  Not if, but when more than 100 lead records are inserted at once (could be through data loader, an apex update, an integration, or whatever), then you'll see the Too many SOQL queries error.

To fix this, you'll need to utilize a separate list or map, and move your SOQL outside of the for loop.

Below is an example of how you might remedy it.  You'll have to test the solution out yourself, of course.

trigger UpdateLeadOwner on Lead (before insert,before update) {
    Set<String> domains = new Set<String>();
    String userRoleId = .. make this a custom setting / non-hardcoded value..
    for (Lead leadInLoop : Trigger.new) {
        domains.add(leadInLoop.Domain__c);
    }

    List<Account> accounts = [Select OwnerId From Account Where Domain__c in :domains and Owner.UserRoleId = :userRoleId];

    for(Lead leadInLoop : Trigger.New){
        for(Account acct : accounts){
            if(leadInLoop.Domain__c == acct.Domain__c){
                leadInLoop.OwnerId = acct.OwnerId;   
            }
        }
    }
}


Gigi.OchoaGigi.Ochoa
You have a SOQL query inside a for loop.  It is best practice not to perform any queries or DML inside a loop.
https://developer.salesforce.com/page/Apex_Code_Best_Practices

Also, are there any other triggers on your Lead object?

I would recommend using a Map to update the Lead Owner.

Here is some code to get you started.  Here, even if you have 200 leads being updated, you only make 1 SOQL query.  Before you would make a SOQL query for each Lead record.

trigger UpdateLeadOwner on Lead (before insert,before update) {
    
    Set<String> domains = new Set<String>();
    Map<Id, String> domainToOwnerMap = new Map<Id, String>();

    for (Lead leadInLoop : Trigger.new) {   
	if(leadInLoop.Domain__c != null) domains.add(leadInLoop.Domain__c);
    }
 
    if(domains.size() > 0){
  	// get list of accounts with matching Domains
        List<Account> acct = [Select OwnerId, Domain__c from Account WHERE Domain__c IN :domains AND Owner.UserRoleId != '00E50000000t0Bf'];
	
	// create a Domain to OwnerId Map
	for(Account a:acct){
		domainToOwnerMap.put(a.Domain__c, a.OwnerId);
	}
   		
    }    
	
    // now loop through your Leads and update Lead Owner using map create above
    for (Lead leadInLoop : Trigger.new) {
   
	if (leadInLoop.LeadSource != 'Contact Us' && leadInLoop.LeadSource != 'Reprint') {
		
		if(domainToOwnerMap.containsKey(leadInLoop.Domain__c)){
			System.debug('account owner id is: ' + domainToOwnerMap.get(leadInLoop.Domain__c);
		    	leadInLoop.OwnerId = domainToOwnerMap.get(leadInLoop.Domain__c);
		}	    
  
    	}

    }
}


Ravikant kediaRavikant kedia
Please read link https://developer.salesforce.com/page/Apex_Code_Best_Practices for future.