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
fiona gentryfiona gentry 

How to Prevent [ First error: Too many query rows: 50001] From Happening in Database.Batchable

Dear gurus,

Here is my batch code ,Now problem is even if it uses Database.Batchable still I am observing the below governor limit error as First error: Too many query rows: 50001 ,is there a way to write a test class which will prevent such occurrences before it actually happens,I found this error after I wrote below ```SOQL```

select id, ApexClass.Name, CompletedDate, CreatedBy.name, Status, ExtendedStatus from AsyncApexJob where CreatedDate = today order by CreatedDate desc
 
global class OnlineRequestAppointmentHandlingBatch implements Database.Batchable<sObject>, Database.AllowsCallouts, Database.stateful   {
						global Set<Id> AptList = new Set<Id> ();
						public static final String STATUS_CANCELED    = 'Canceled';
						public static final String REASON_FOR_CANCEL    = 'Other (NOT Requested by Cust)';
						List<Event_Log__c> inputEventLogs = New List<Event_Log__c>();
						List<ServiceAppointment> ApptsToCancel = new List<ServiceAppointment>();
						public OnlineRequestAppointmentHandlingBatch(List<Event_Log__c> eventLogList){
							this.inputEventLogs = eventLogList;
						}
						
						global Database.QueryLocator start(Database.BatchableContext BC) {
							Set<String> strReqDetailIds =  new Set<String>();
							Set<Id> setStores 			= new Set<Id>();
							List<Store__c> storesList = new List<Store__c>();
							for(Event_Log__c elObj: inputEventLogs){
								strReqDetailIds.add(elObj.Event_Record_ID__c);
							}            
							for(Store_Request_Detail__c srdRec : [Select id, Store__c from Store_Request_Detail__c where id in :strReqDetailIds]){
								setStores.add(srdRec.Store__c);  
							}
							storesList = [select Id from Store__c where Id IN:setStores];
							
							AptList.addAll(TM_AppointmentCancellationHandler.AppointmentCancellation(storesList));
							//String query = 'select Id from Store__c where Id IN:setStores';
							String query = 'SELECT Id, status,reschedule__c,reason_for_cancel__c  FROM ServiceAppointment WHERE Id IN : AptList';
							return Database.getQueryLocator(query);
						}
						
						global void execute(Database.BatchableContext bc,List<ServiceAppointment> scope) {      
							{
								For (ServiceAppointment SA:scope)
								{
									SA.status               = STATUS_CANCELED;
									SA.reschedule__c        = false;
									SA.reason_for_cancel__c = TM_Util.check( REASON_FOR_CANCEL );
									ApptsToCancel.add(SA);
								}
								if(!ApptsToCancel.isEmpty()){
									TM_SendEmailAppointmentWrapper.AutoEmailCallout = false;
									Database.SaveResult[] srList = database.update(ApptsToCancel, false);
									system.debug('srList=='+srList);
								}
						}
						}
						
						global void finish(Database.BatchableContext BC) {
							system.debug('AptList=='+AptList);
							if(!AptList.isEmpty()){
								system.debug('CMT_CANCEL_APPOINTMENT_EMAILS_BATCH_SIZE::'+OnlineRequestService.CMT_CANCEL_APPOINTMENT_EMAILS_BATCH_SIZE);
								Database.executeBatch(new TM_CancelBlockStoreAppointmentEmails(AptList),OnlineRequestService.CMT_CANCEL_APPOINTMENT_EMAILS_BATCH_SIZE);
							}
						}
					}

Regards,
Fiona
AbhishekAbhishek (Salesforce Developers) 
Fiona,

There is a limit to the number of records that can be retrieved by the SOQL Query which is 50000 records. Attempting to query the records having a number more than this will give the error which you are getting. To query the records more than their limit, you need to use a Batch Class which provides a fresh limit of 50k records by resetting the limits.


Because Apex runs in a multitenant environment, the Apex runtime engine strictly enforces limits to ensure that runaway Apex code or processes don’t monopolize shared resources. If some Apex code exceeds a limit, the associated governor issues a runtime exception that cannot be handled. These limits count for each Apex transaction. For Batch Apex, these limits are reset for each execution of a batch of records in the execute method.

In a SOQL query with parent-child relationship subqueries, each parent-child relationship counts as an extra query. These types of queries have a limit of three times the number for top-level queries. The limit for subqueries corresponds to the value that Limits.getLimitAggregateQueries() returns.The row counts from these relationship queries contribute to the row counts of the overall code execution. This limit doesn’t apply to custom metadata types. In a single Apex transaction, custom metadata records can have unlimited SOQL queries. In addition to static SOQL statements, calls to the following methods count against the number of SOQL statements issued in a request.Database.countQuery
Database.getQueryLocator
Database.query.


You are seeing this error due to the cap on the number of updates that Salesforce will allow on a DML. The max is 50K. You can reach out to Salesforce to see if they can make an exception for your org to increase your query rows governor limit to 100,000 rows.


For further reference, you can check this too,

https://www.levelupsalesforce.com/too-many-query-rows-50001-in-salesforce

https://www.thinkaholics.com/salesforce/too-many-query-rows-50001-read-only-is-your-friend/


Let me know if it helps you and close your query by marking it as solved so that it can help others in the future.

Thanks.