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
Streepie24Streepie24 

Too many SOQL queries

Hi there,

 

I keep getting the "Too many SOQL queries" error when trying to deploy my apex class.

I tried a lot of constructions but can't figure out how to construct this class so that i don't get those errors...!?

 

I get the errors when i unmark the /* ---->>>*/ marked rows...

 

Is there somebody who could help me to get my class deployed?

 

 

public class Taak_tbv_Factuur { public static integer TESTVAR = 0; //Lijsten tbv opslaan gevonden Achterstallige facturen; om later te verwerken en geen bulk limits tegen te komen public static List<Achterstallige_factuur__c> Dag8Facturen = new List<Achterstallige_factuur__c>(); public static List<Account> Dag8Accounts = new List<Account>(); public static List<Integer> Dag8Taken = new List<Integer>(); public static List<Achterstallige_factuur__c> Dag22Facturen = new List<Achterstallige_factuur__c>(); public static List<Account> Dag22Accounts = new List<Account>(); public static List<Achterstallige_factuur__c> Dag42Facturen = new List<Achterstallige_factuur__c>(); public static List<Achterstallige_factuur__c> Dag50Facturen = new List<Achterstallige_factuur__c>(); //haal Id van SYSTEM op public static User sys = [SELECT Id FROM User WHERE Alias =: 'SYSTE']; //haal MKP van SYSTEM op public static User mkp = [SELECT Id FROM User WHERE Alias =: 'MKP']; @Future public static void Check_Achterstallig(){ // zoek naar de nog niet afgehandelde achterstallige facturen Achterstallige_factuur__c[] Af = [SELECT Id, Relatie__c, CreatedDate, Status__c FROM Achterstallige_factuur__c WHERE Status__c != 'Afgehandeld']; for(Achterstallige_factuur__c f: Af){ // bereken leeftijd van de achterstallige factuur entry Date OPVOERDATUM = date.valueof(string.valueof(f.CreatedDate)); Date VANDAAG = Date.today(); integer leeftijd = OPVOERDATUM.daysbetween(VANDAAG); if(leeftijd >= 50 || TESTVAR == 4){ // bestaande taak mkp op afgesloten zetten en nieuwe taak voor mkp aanmaken en zet achterstallige factuur op "Loopt bij Incasso" Dag50Facturen.Add(f); } else if(leeftijd >= 42 || TESTVAR == 3){ // bestaande taak mkp op afgesloten zetten en nieuwe taak voor mkp aanmaken en zet achterstallige factuur op "Laatste sommatie versturen..." Dag42Facturen.Add(f); } else if(leeftijd >= 22 || TESTVAR == 2){ // Als het nabellen van de AM niet heeft geholpen laten we F&A terugbellen, 22 dagen na invoeren achterstallige factuur Account a = [SELECT OwnerId, Id FROM Account WHERE Id =: f.Relatie__c limit 1]; Dag22Facturen.Add(f); Dag22Accounts.Add(a); } else if(leeftijd >= 8 || TESTVAR == 1){ // 8 dagen nadat de achterstallige factuur is ingevoerd maken we de eerste taak aan om te laten bellen door AM van de betreffende relatie Account a = [SELECT OwnerId, Id FROM Account WHERE Id =: f.Relatie__c limit 1]; integer i = [SELECT Count() FROM Task WHERE WhatId =: f.Id and CreatedById =: sys.Id limit 1]; Dag8Facturen.Add(f); Dag8Accounts.Add(a); Dag8Taken.Add(i); } } for (integer afactuur = 0; afactuur < Dag50Facturen.size(); afactuur++){ Achterstallige_factuur__c ach=Dag50Facturen[afactuur]; /* ---->>> */ //MaakTaakDag50(ach); } for (integer afactuur = 0; afactuur < Dag42Facturen.size(); afactuur++){ Achterstallige_factuur__c ach=Dag42Facturen[afactuur]; /* ---->>> */ //MaakTaakDag42(ach); } for (integer afactuur = 0; afactuur < Dag22Facturen.size(); afactuur++){ Achterstallige_factuur__c ach=Dag22Facturen[afactuur]; account a = Dag22Accounts[afactuur]; /* ---->>> */ //MaakTaakDag22(ach, a); } for (integer afactuur = 0; afactuur < Dag8Facturen.size(); afactuur++){ Achterstallige_factuur__c ach=Dag8Facturen[afactuur]; account a = Dag8Accounts[afactuur]; integer i = Dag8Taken[afactuur]; //taak mag nog niet bestaan if(i==0){ MaakTaakDag8(ach, a); } } } private static void MaakTaakDag8(Achterstallige_factuur__c ach, account a){ // 8 dagen nadat de achterstallige factuur is ingevoerd maken we de eerste taak aan om te laten bellen door AM van de betreffende relatie //Maak de taak aan Task[] newTask = new Task[0]; newTask.add(new Task(Description = 'Relatie nabellen tbv achterstallige betaling factuur (FASE 1 van 4)', Priority = 'Normal', Status = 'Nog te Starten', Subject = 'Achterstallige factuur', IsReminderSet = true, ReminderDateTime = System.now(), OwnerId = a.OwnerId, WhatId = ach.Id) ); insert newTask; } private static void MaakTaakDag22(Achterstallige_factuur__c ach, account a){ // Als het nabellen van de AM niet heeft geholpen laten we F&A terugbellen, 22 dagen na invoeren achterstallige factuur // update bestaande taak naar afgesloten en maak een nieuwe aan Task[] Tsk = [SELECT Id FROM Task WHERE WhatId =: ach.Id and CreatedById =: sys.Id and OwnerId =: a.OwnerId and status != 'Afgesloten']; for(Task T: Tsk){ T.status = 'Afgesloten'; T.IsReminderSet = false; Update T; } // Als de taak voor MKP nog niet bestaat dan aanmaken integer i = [SELECT count() FROM Task WHERE WhatId =: ach.Id and CreatedById =: sys.Id and OwnerId =: mkp.Id and status != 'Afgesloten' limit 1]; if(i == 0){ // Maak taak aan Task[] newTask = new Task[0]; newTask.add(new Task(Description = 'Relatie nabellen tbv achterstallige betaling factuur (FASE 2 van 4)', Priority = 'Normal', Status = 'Nog te Starten', Subject = 'Achterstallige factuur', IsReminderSet = true, ReminderDateTime = System.now(), OwnerId = mkp.Id, WhatId = ach.Id) ); insert newTask; } } private static void MaakTaakDag42(Achterstallige_factuur__c ach){ // bestaande taak mkp op afgesloten zetten en nieuwe taak voor mkp aanmaken en zet achterstallige factuur op "Laatste sommatie versturen..." Task[] Tsk = [SELECT Id, Description FROM Task WHERE WhatId =: ach.Id and CreatedById =: sys.Id and OwnerId =: mkp.Id and status != 'Afgesloten' ]; for(Task T: Tsk){ if(T.Description == 'Relatie nabellen tbv achterstallige betaling factuur (FASE 2 van 4)'){ T.status = 'Afgesloten'; T.IsReminderSet = false; Update T; // nieuwe taak aanmaken voor MKP tbv laatste sommatie Task[] newTask = new Task[0]; newTask.add(new Task(Description = 'Laatste sommatie versturen (FASE 3 van 4)', Priority = 'Normal', Status = 'Nog te Starten', Subject = 'Achterstallige factuur', IsReminderSet = true, ReminderDateTime = System.now(), OwnerId = mkp.Id, WhatId = ach.Id) ); insert newTask; // status van de achterstallige factuur bijwerken ach.Status__c = 'Laatste sommatie is verstuurd'; update ach; } } } private static void MaakTaakDag50(Achterstallige_factuur__c ach){ // bestaande taak mkp op afgesloten zetten en nieuwe taak voor mkp aanmaken en zet achterstallige factuur op "Loopt bij Incasso" Task[] Tsk = [SELECT Id, Description FROM Task WHERE WhatId =: ach.Id and CreatedById =: sys.Id and OwnerId =: mkp.Id and status != 'Afgesloten' ]; for(Task T: Tsk){ if(T.Description == 'Laatste sommatie versturen (FASE 3 van 4)'){ T.status = 'Afgesloten'; T.IsReminderSet = false; Update T; // nieuwe taak aanmaken voor MKP tbv laatste sommatie Task[] newTask = new Task[0]; newTask.add(new Task(Description = 'Factuur aanbieden ter incasso (FASE 4 van 4)', Priority = 'Normal', Status = 'Nog te Starten', Subject = 'Achterstallige factuur', IsReminderSet = true, ReminderDateTime = System.now(), OwnerId = mkp.Id, WhatId = ach.Id) ); insert newTask; // status van de achterstallige factuur bijwerken ach.Status__c = 'Loopt bij incasso'; update ach; } } } }

 

 
Best Answer chosen by Admin (Salesforce Developers) 
AlanPerkinsAlanPerkins

Hi Streepie24,

 

Your problem is that you have an insert statement in the middle of a for loop.

 

You need to only touch the database when you need to.

 

Any time you do a SELECT, an INSERT, UPDATE, DELETE or UNDELETE, you need to make sure that it is not in the middle of a for loop.

 

To fix your code, add any records you want to modify to a list of the correct type in your for loop. Only touch the database when you have completed the for loop.

 

Here is a simple example:

 

 

list<MyObject__c> MyObjects = [select ID, MyField__c from MyObject__c]; list<MyOtherObject__c> MyOtherObjects = new list<MyOtherObject>(); for (MyObject__c MyObject:MyObjects) { //Do some stuff to my objects //Create a new MyOtherObject //Add your new MyOtherObject to your MyOtherObjects } update MyObjects; insert MyOtherObjects; //3 database touches in all: = 3/100 SOQL statements. HTH

 

 

 

All Answers

AlanPerkinsAlanPerkins

Hi Streepie24,

 

Your problem is that you have an insert statement in the middle of a for loop.

 

You need to only touch the database when you need to.

 

Any time you do a SELECT, an INSERT, UPDATE, DELETE or UNDELETE, you need to make sure that it is not in the middle of a for loop.

 

To fix your code, add any records you want to modify to a list of the correct type in your for loop. Only touch the database when you have completed the for loop.

 

Here is a simple example:

 

 

list<MyObject__c> MyObjects = [select ID, MyField__c from MyObject__c]; list<MyOtherObject__c> MyOtherObjects = new list<MyOtherObject>(); for (MyObject__c MyObject:MyObjects) { //Do some stuff to my objects //Create a new MyOtherObject //Add your new MyOtherObject to your MyOtherObjects } update MyObjects; insert MyOtherObjects; //3 database touches in all: = 3/100 SOQL statements. HTH

 

 

 

This was selected as the best answer
ThomasTTThomasTT

Actually, you're getting error message "Too many SOQL queries", so the number of SELECT query is the problem. Of course, it's because you query in the for-loop. That's the proble.

 

You still have the next big wall "Governor Limit: the number of query rows (10,000 from VF pages, 1,000 from triggers), but here is how we usually avoid the number of queries governor limist:

 

 

Set<Id> idSetAllWhatIds = new Set<Id>(); Set<Id> idSetAllOwnerIds = new Set<Id>(); // Prepare for the sets avobe for all possible Ids Task[] Tsk = [ SELECT Id, Description, whatId, OwnerId FROM Task WHERE WhatId in :idSetAllWhatIds and CreatedById =: sys.Id and OwnerId in :idSetAllOwnerIds status != 'Afgesloten' ]; Map<String, Task> tskMapWhatAndWho = new Map<String, Task>(); Map<Id, Task> tskMapId = new Map<Id, Task>(); for(Task t : Tsk){ tskMapWhatAndWho.put(t.whatId+'|'+t.ownerId, t); tskMapId.put(t.id, t); } // use the maps for the following process

 

And you have to make efforts to reduce the number of SOQL by yourself. For example, by using the map or new map like Map<String, List<Task>>, you can count the number of Task for MKP user without another select count() query.

 

Of course, you have to do the same thing for other objects.

 

ThomasTT