There is a loop hole here . This trigger is also firing whenever we are updating the other fields in the same trigger. I guess there has to be a oldmap check for the name here in order to avoid such scenario as during the course there are multiple triggers build on same object.
@sfdcninjas Жыл бұрын
Hi Stuti , we cannot say that it is loophole actually this trigger is checking duplicates whenever any fields updates but the thing is it is only checking for names.
@mayanksharma139 Жыл бұрын
@@sfdcninjas As Stuti said, We have to compare the old n value in order to prevent duplication otherwise it throw an error even if user update the record without chaning it's name as the record having the same name present in database
@krishnaCasukhela Жыл бұрын
@@sfdcninjas, normally account names are not updated from the front end. so I don't understand why you are using trigger.isUdpate, it should be only trigger.isInsert..
@footballtalkswithsoham443011 ай бұрын
Thanks for the help
@DS123996 ай бұрын
instead of creating a loop for list to map we can use Map existingAccMap = new Map(accList);
@sfdcninjas6 ай бұрын
nice suggestion Divya thanks
@agamyashvant55452 ай бұрын
at line 17, we need to add null check isn't?
@prasadpj8577 Жыл бұрын
This will fail for update operation when we click edit and save without even changing name
@naveenyalamala4 ай бұрын
public static void preventDuplicateRecord(List accList){ // Collect unique account names (normalized to lowercase) Set newAccNames = new Set(); for (Account acc : accList) { if (acc.Name != null) { newAccNames.add(acc.Name.toLowerCase()); } } // Query existing accounts with names in the set List existingAccounts = [ SELECT Id, Name FROM Account WHERE Name IN :newAccNames ]; // Collect existing account names and their IDs Set existingAccNames = new Set(); Map existingNameToIdMap = new Map(); for (Account acc : existingAccounts) { existingAccNames.add(acc.Name.toLowerCase()); existingNameToIdMap.put(acc.Name.toLowerCase(), acc.Id); } // Flag duplicate records for (Account acc : accList) { if (acc.Name != null) { String normalizedName = acc.Name.toLowerCase(); // Check if the name exists and if it's not the same as the current record if (existingAccNames.contains(acc.Name.toLowerCase()) && !existingNameToIdMap.get(acc.Name.toLowerCase()).equals(acc.Id)) { acc.addError('Duplicate Account Name detected: ' + acc.Name); } } } }
@dharmeshgupta3957 Жыл бұрын
very informative and helpful!!
@sfdcninjas Жыл бұрын
Thank you Dharmesh
@ambritkumarsahu5179 Жыл бұрын
Bro.. instead of using a map , can't we use a List there to store the Names.. Because we are not using the Values of the Map, only using the Keys.. Isn't it? Or am I missing something?
@sfdcninjas Жыл бұрын
Hi Buddy , sorry for late reply , List can have duplicate values that's why we are using map here.
@sagarbora77689 ай бұрын
@@sfdcninjas But we could use set it's gonna have distinct values, Correct me if I'm wrong.
@naveenyalamala4 ай бұрын
You are trying to insert 4 Account records, all with the same name, and that name does not currently exist in the database. Will it allow Insertion ?
@JShorts5114 ай бұрын
The following code will not allow /*Trigger Scenario: Write a trigger to prevent duplicate accounts based on name whenever an Account is inserted or updated. Scenario is to validate records before they are saved to database. so we use before trigger. context variables to access runtime contexts are Trigger.isInsert and Trigger.isUpdate*/ trigger AccountTrigger on Account(before insert,before update){ //set to collect Account Name from triggering records. List accNames=new List(); //accessing run time context if(Trigger.isBefore){ if(Trigger.isInsert){ //iterating over triggering records for(Account acc:Trigger.new){ accNames.add(acc.Name); } } if(Trigger.isUpdate){ //iterating over triggering records for(Account acc:Trigger.new){ //checking whether the account's Name is changed or not if(acc.Name != Trigger.oldMap.get(acc.Id).Name){ accNames.add(acc.Name); } } } } List accList=[SELECT Id,Name FROM Account WHERE Name IN:accNames]; set accNameSetToCheckDups=new set(); //Map to get number of accounts with same name Map accNamesCountwithName=new Map(); //iterating over accNames if(!accNames.isEmpty()){ for(String acctName:accNames){ if(!accNamesCountwithName.containsKey(acctName)){ accNamesCountwithName.put(acctName,0); }else { Integer count=accNamesCountwithName.get(acctName)+1; accNamesCountwithName.put(acctName,count); } } } //iterating over accList to collect existing names if(!accList.isEmpty()){ for(Account acc:accList){ accNameSetToCheckDups.add(acc.Name); } } //iterating over Triggering records to prevent duplicates if(!accNameSetToCheckDups.isEmpty() || accNamesCountwithName.keySet() !=null ){ //if triggering records has the same name more than one (If we are inserting /updating with same name at a time) for(Account acc:Trigger.new){ if(accNamesCountwithName.get(acc.Name)>1 || accNameSetToCheckDups.contains(acc.Name)){ acc.addError('Account already exists with the same name'); } } } }
@naveenyalamala4 ай бұрын
@@JShorts511 thank you
@jatinneelay59262 ай бұрын
there should be if else and in else we should add non duplicate record in map so that within trigger scope we dont insert duplicates
@rahulkumbhare5454 Жыл бұрын
Hi SFDC Ninja, can't we simply check the size of accList and determine duplicate account name present or not? The accList will have values only if the Accounts with the given names are already present. So, if the size is more than 0, it means we already have accounts in the database with name which are being inserted. Please correct if this understanding is wrong. Thanks
@sfdcninjas Жыл бұрын
Hi Rahul , see Checking the size of accNames instead of accList may not be suitable for bulk records. also Without querying the accList, you won't have access to the actual existing accounts with duplicate names. This means you cannot perform any specific actions or validations on those existing accounts. It may limit your ability to handle duplicates effectively or implement customized logic based on the existing account records.
@soumya17132 ай бұрын
if you have more than 50k records then how can you handle it
@opeyemi_salesforce_journey2 ай бұрын
you might need to go for more async solution like queueable or batch apex
@prasadpj8577 Жыл бұрын
Please upload a scenario to avoid trigger using Map
@sfdcninjas Жыл бұрын
Hi Prasad sure i will try to create a video on it .
@rohantelang1817 Жыл бұрын
In this solution, there is many "for loops".can any one provide solution by reducing "for loops"?
@lokeshv8999 Жыл бұрын
trigger CandidateTrigger on Account(Before insert,Before Update){ if(trigger.isbefore && (trigger.isinsert ||trigger.isUpdate ){ listaccrecord=[select id,name from account]; for(Account accnew:Trigger.new){ for(Account accold:accrecord){ if(accnew.name==accold.name){ accnew.name.adderror('Duplicate Name cannot be entered again'); } } } } }
@SathishKumar-ok6tu10 ай бұрын
@@lokeshv8999 List accrecord = [select id,name from account]; As per Salesforce Governor Limits, SOQL will return maximum 50K records. This will fail if our org contains more than 50K account records. Also, this code contains nested for loop which will affect performance.
@praveenbuddi190 Жыл бұрын
goto VScode settings--- settings- search for Font -- default is 14- to increase- 20-24 font size...
@sfdcninjas Жыл бұрын
Thank you again
@praveenbuddi190 Жыл бұрын
bro, small suggetion increse font size.
@sfdcninjas Жыл бұрын
sure bro and thank you for suggestion
@ramadevikantamani3057 Жыл бұрын
Scenario will fail when we update other fields in the account other than name .
@sfdcninjas Жыл бұрын
Hi , In this scenario I have explained trigger to prevent duplication of account record based only on Name field you can add other fields to prevent duplication. Thank you
@deboleenadutta14489 ай бұрын
what is the peoblem with the simple solution given below.. if anybody has idea let me know trigger PreventDupl on Account(before Insert , before delete){ if(trigger.isBefore && trigger.isDelete){ for(account acc : trigger.new){ integer countedRec = [select count(id) from Account where name = acc.name]; if(countedRec > 0){ acc.addError('Already an account is existing with the provided name'); } } } }
@rupesh-patil0118 ай бұрын
@deboleenadutta1448 You are doing SOQL inside for loop. It will hit the governor limit and before delete is not required.
@deboleenadutta14488 ай бұрын
@@rupesh-patil011 thanks … yes before delete is my mistake…
@sfdcakshul Жыл бұрын
Informative 👍
@sfdcninjas Жыл бұрын
Thank you
@praveennanda75217 ай бұрын
trigger AccountTrigger on Account(before insert, before update) { if(trigger.isbefore && (trigger.isinsert || trigger.isupdate)) { for(Account acc :trigger.new) { Integer accountCount = [Select count() from Account where Name =: acc.Name]; if(accountCount>0) acc.Name.addError('Please enter the last name as uniquly'); } } }
@ShikhaKanaujia-k7d7 ай бұрын
avoid using SOQL inside for loop
@BusraYildiz-t3u8 ай бұрын
trigger ApexTrigger6 on Account (before insert,before Update) { Set Names = new Set(); If(Trigger.isBefore){ For(Account acc: Trigger.new){ if(trigger.isInsert|| acc.Name!=trigger.oldMap.get(acc.id).Name){ Names.add(acc.Name); } } } List ExistingName = New List(); For(Account acc:[Select Name, Id From Account Where Name In:Names]){ ExistingName.add(acc.Name); } For(Account acc: trigger.new){ if(ExistingName.Contains(acc.name)) acc.Name.addError('duplicate'); } } here is another approach