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
NANCY1NANCY1 

How to check the contact duplication while editing??

Hi,

 

Using the below given trigger i am able to prevent user from being creating a contact with an existing Email Address, but i also need to check this while changing an existing contact's email address... i mean even for an existing contacts if the user try to change an email address with an existing email address.. the trigger should get fired??

 

 

 

trigger ContactDuplicateTrigger on Contact (before insert) {
   for (Contact c : Trigger.new){
     
      Contact[] contacts= [select id from Contact where Email = :c.Email];
     
      if (contacts.size() > 0) {
          c.Email.addError('Contact cannot be created - Contact already exists');
      }   
   }
}

 

 

Best Answer chosen by Admin (Salesforce Developers) 
bob_buzzardbob_buzzard

You may run into problems using this mechanism with bulk changes (e.g. inserts from data loader), as you have embedded a SOQL query inside a loop which may break governor limits.  You'd do better to query against all emali addresses and then figure out afterwards which are the duplicates if  you expect to receive bulk inserts/updates.

 

It looks like you'll need to make your trigger work before insert and before update in order to achieve this.

 

Something like the following I reckon - note that the code that I have added is also not bulk safe:

 

 

trigger ContactDuplicateTrigger on Contact (before insert, before update) {
   if (Trigger.isInsert)
   {
      for (Contact c : Trigger.new){
     
         Contact[] contacts= [select id from Contact where Email = :c.Email];
     
         if (contacts.size() > 0) {
             c.Email.addError('Contact cannot be created - Contact already exists');
         }   
      }
   }
   else if (Trigger.isUpdate)
   {
       for (Contact c : Trigger.new)
       {
          Contact oldC=Trigger.oldMap.get(c.id);
          if (c.Email != oldC.Email)
          {
             Contact[] contacts= [select id from Contact where Email = :c.Email];
     
             if (contacts.size() > 0) 
             {
                c.Email.addError('Contact cannot be updated - Contact with this email address already exists');
             }
              
          }
       }
   }
}

 

 

All Answers

bob_buzzardbob_buzzard

You may run into problems using this mechanism with bulk changes (e.g. inserts from data loader), as you have embedded a SOQL query inside a loop which may break governor limits.  You'd do better to query against all emali addresses and then figure out afterwards which are the duplicates if  you expect to receive bulk inserts/updates.

 

It looks like you'll need to make your trigger work before insert and before update in order to achieve this.

 

Something like the following I reckon - note that the code that I have added is also not bulk safe:

 

 

trigger ContactDuplicateTrigger on Contact (before insert, before update) {
   if (Trigger.isInsert)
   {
      for (Contact c : Trigger.new){
     
         Contact[] contacts= [select id from Contact where Email = :c.Email];
     
         if (contacts.size() > 0) {
             c.Email.addError('Contact cannot be created - Contact already exists');
         }   
      }
   }
   else if (Trigger.isUpdate)
   {
       for (Contact c : Trigger.new)
       {
          Contact oldC=Trigger.oldMap.get(c.id);
          if (c.Email != oldC.Email)
          {
             Contact[] contacts= [select id from Contact where Email = :c.Email];
     
             if (contacts.size() > 0) 
             {
                c.Email.addError('Contact cannot be updated - Contact with this email address already exists');
             }
              
          }
       }
   }
}

 

 

This was selected as the best answer
NANCY1NANCY1

Many Thanks.. it worked...

irlrobinsirlrobins

Bulk friendly version:

 

trigger ContactDuplicateTrigger on Contact (before insert, before update) {
	List<Id> contactids = new List<Id>();
	Map<Id,String> contactmap = new Map<Id,String>();
	for(Contact c : Trigger.new) {
		contactids.add(c.id);
	}
	List<Contact> contacts = [SELECT Id, Email from Contact where ID IN :contactids];
	for(Contact c : contacts) {
		contactmap.put(c.Id,c.email);
	}

   if (Trigger.isInsert)
   {
      for (Contact c : Trigger.new){
     
         if(contactmap.get(c.id)!=null){
             c.Email.addError('Contact cannot be created - Contact already exists');
         }   
      }
   }
   else if (Trigger.isUpdate)
   {
       for (Contact c : Trigger.new)
       {
          Contact oldC=Trigger.oldMap.get(c.id);
          if (c.Email != oldC.Email)
          {
            if(contactmap.get(c.id)!=null){
             c.Email.addError('Contact cannot be created - Contact already exists');
         }   
        }
       }
   }
}

 

bob_buzzardbob_buzzard

Unfortunately these lines:

 

 

for(Contact c : Trigger.new) {
		contactids.add(c.id);
	}

 

will cause problems for before insert triggers - the sobjects contained in Trigger.new don't have ids (which is also why the Trigger.newMap is unavailable for before insert).  In this case the records would need to be handled via another key - most likely email address.  

 

I also think there's some confusion here - this version of the trigger appears to be checking that a contact with the same id doesn't already exist - the original use case was to check that no contact with the same email address exists.

 

 

irlrobinsirlrobins

Ugh, how embarassing. I really shouldn't post something when I'm trying to rush out the door.

 

Would this work? Or would the initial select break limits as well?

 

trigger ContactDuplicateTrigger on Contact (before insert, before update) {
	Map<String,Id> contactemailmap = new Map<String,Id>();
	
	List<Contact> contacts = [SELECT Id, Email from Contact];
	for(Contact c : contacts) {
		contactemailmap.put(c.email,c.id);
	}

   if (Trigger.isInsert)
   {
      for (Contact c : Trigger.new){
     
         if(contactemailmap.get(c.email)!=null){
             c.Email.addError('Contact cannot be created - Contact already exists');
         }   
      }
   }
   else if (Trigger.isUpdate)
   {
       for (Contact c : Trigger.new)
       {
          Contact oldC=Trigger.oldMap.get(c.id);
          if (c.Email != oldC.Email)
          {
            if(contactemailmap.get(c.email)!=null){
             c.Email.addError('Contact cannot be created - Contact already exists');
         }   
        }
       }
   }
}

 

bob_buzzardbob_buzzard

It stands a chance of breaking governor limits if there are more than 50k contacts.

 

I'd be inclined to create a map of the new/updated contacts keyed by email address (contByEmailMap), then pull back a list of all contacts that have that email address from the database.  Then iterate the contacts returned from the database and get the matching contact(s) from contByEmailMap based on the email address.

 

There's a couple more gotchas though - contByEmailMap needs its values to be lists of contacts (as in bulk mode there may be more than one with the same email) and it would also need to check that there are no duplicates in the contacts being processed by the trigger - i.e. no dupes in the database but the same email appearing twice in trigger.new.

 

This is why I didn't put up any bulk safe code - I've implemented this once before and it gets a little unwieldy.