function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
PravinPravin 

too many dml rows 10001

Hi Team,

I am working on batch job which is operating on lots of records. I need to create opportunity sharing based on account sharing.I have written a batch job which is woking on  account records 1000 as batch size. First i am taking all opportunity records linked to those accounts and passing the id of account and opportunity to a different normal apex class. In the for loop i am  iterating on all the linked opportunity records (more than 10000 opp records linked to 1000 account records).When i am trying to create opp share records for those opp records and upserting them getting the below error
                                     "too many dml rows 10001"
Please tell me the  solution for this( instead of reducing the batch size).

My code snippet
Batch Job Execute method

global void execute(Database.BatchableContext BC, List<Sobject> scope){
        List<Opportunity> opptyList = (List<Opportunity>)scope;
       // Set<ID> oppIds = new Set<ID>():
         Set<ID> accountIds = new Set<ID>();
        Map<ID,Set<ID>> acctOppIDs = new Map<ID,Set<ID>>();
        for(Opportunity oppty : opptyList) {
            if(oppty.Sold_To_Account__c != null){
             //   oppIds.add(oppty.id);
                accountIDs.add(oppty.Sold_To_Account__c);
                if(acctOppIDs.get(oppty.Sold_To_Account__c) == null) {
                    acctOppIDs.put(oppty.Sold_To_Account__c, new Set<ID>());
                }
                acctOppIDs.get(oppty.Sold_To_Account__c).add(oppty.id);
            }
            //Update Opportunities Flag
          oppty.SoldToChanged__c = false;
         
        }
        System.SavePoint pSavepoint = null;
        if(accountIDs.size() >0) {
            try {
             pSavepoint = Database.setSavepoint(); 
             ShareOpportunitiesUtil.shareOpptys(accountIDs, acctOppIDs);
             //Update Opportunities Flag
             upsert opptyList;
            }catch(Exception ex) {
                errorMsg +=ex.getMessage()+'\n';
              Database.rollback(pSavepoint);
            }
        }
    }

My normal Class
public without sharing class ShareOpportunitiesUtil {
    public static void shareOpptys(Set<ID> accountIDs, Map<ID,Set<ID>> acctOppIDs) {
       
        List<OpportunityShare> oppSharesList = new List<OpportunityShare> ();
        for(AccountShare accShare :[Select a.UserOrGroupId, a.RowCause, a.OpportunityAccessLevel,
                                     a.AccountAccessLevel, a.AccountID
                                     From AccountShare a
                                     where accountID in :accountIDs]) {
      OpportunityShare oppShare = null;
      for (String oppId :acctOppIDs.get(accShare.AccountID)) {
          oppShare = new OpportunityShare();
          oppShare.OpportunityId = oppId;
          oppShare.UserOrGroupId = accShare.UserOrGroupId;
          oppShare.OpportunityAccessLevel = 'Edit'; //HA changed to Edit accShare.AccountAccessLevel;
          oppSharesList.add(oppShare);
      }
    }
    try {
        Database.upsert(oppSharesList,false);
    }catch(Exception ex) {
        System.debug('Exception occured');
        throw ex;
    }
    }
}

Appreciate your help.

Thanks
Pravin
NehalNehal (Salesforce Developers) 
Hi,

This error occurs usually when the total number of records processed by DML statements in greater than 10,000 ( Hitting on governor limit) and you can use for loop technique to reduce the number of records processed in single DML operation.

Kindly refer the below sample code to avoid this error:
Make a list here say:l1
Integer n=list.size();
Integer i=n/2;
For(integer j=0;j<10000;j++)
{
L1.add(list[i]);
}
Update l1;

Similarly you can iterate for next half set of records and can update your records in sets.

Note :This is a sample code and you need to modify this code as per your business requirements

Also you can try to populate the list and then do DML out from the loop. Please put the all DML statement outside from the for loop.

Further, I am providing you few links as below for your future reference:
1.https://help.salesforce.com/apex/HTViewSolution?urlname=Too-many-DML-rows-in-Apex-when-inserting-1327109077381&language=en_US
2.http://salesforce.stackexchange.com/questions/23253/how-does-salesforce-calculate-dml-rows-what-is-included-to-dml-rows-count
3.http://salesforce.stackexchange.com/questions/12514/system-limitexception-too-many-dml-rows-10001
4.http://salesforce.stackexchange.com/questions/15228/how-to-avoid-dml-insert-update-limit-of-10-000-rows-when-running-anonymous-apex
5.http://www.faqoverflow.com/salesforce/12514.html

" I hope this information has been helpful. If this has helped resolve your issue, please let us know by marking the post as "Best Answer" to help others in the community with similar questions. "
nbknbk
What is batch size you used to call batch class. Try to reduce the batch size to 10 or 20 based on your data in the org. Example snippet is below.

String query = 'SELECT id,name FROM Account WHERE id not in (select accountid from Contact )';  
BatchClass_InsertContacts batchApex = new BatchClass_InsertContacts(query );
 ID batchprocessid = Database.executeBatch(batchApex,10);

Thanks,
Krishna