In Salesforce, duplicate records such as Leads, Contacts, Cases, or Accounts can complicate data management and affect productivity. Merging these records is crucial for consolidating data and maintaining a clean database. Join us to learn about Merging Records in Salesforce with Apex.
There are two primary ways to handle this in Apex:
- Using the merge statement.
- Using the Database.merge() method for more advanced error handling.
In this post, we’ll explore both approaches, complete with examples and best practices for using each.
Approach 1: Using the Apex ‘merge’ Statement:
The merge statement is a simple way to merge up to three records of the same type in Salesforce. It allows you to combine records into a master record while automatically deleting the other records and reassigning related records (e.g., contacts or opportunities) to the master.
Example: Merging Two Accounts Using merge:
Here’s an example where we merge two Account records. One of the accounts has a related Contact, which will be reparented to the master account after the merge.
Here’s the merge operation for two Account records in Apex:
AccountMergeExample Class:
public class AccountMergeExample {
public static void mergeAccountsExample(Account masterAccount, Account duplicateAccount) {
// Merge the two accounts, with with ‘merge’ operator
try {
merge masterAccount duplicateAccount;
System.debug('Merge successful. Master Account ID: ' + masterAccount.Id);
} catch (DmlException e) {
System.debug('An error occurred while merging accounts: ' + e.getMessage());
}
}
}
AccountMergeExampleTest Test Class:
@isTest
public class AccountMergeExampleTest {
@isTest
static void testMergeAccounts(){
List<Account> accList = new List<Account>{
new Account(name='Master Account'),
new Account(name='Duplicate Account')
};
insert accList;
Account masterAcct = [Select id, name from Account where name = 'Master Account' limit 1];
Account mergeAcct = [Select id, name from Account where name = 'Duplicate Account' limit 1];
Contact con = new Contact(FirstName = 'Joe', LastName = 'Merged', accountId = mergeAcct.id);
insert con;
AccountMergeExample.mergeAccountsExample(masterAcct, mergeAcct);
masterAcct = [Select id, name, (Select id, LastName from Contacts) from Account where Id =:masterAcct.id];
// Once the account is merged with the master account,
// the related contact should be moved to the master record.
System.assert(masterAcct.getSObjects('Contacts').size() > 0);
System.assertEquals('Merged', masterAcct.getSObjects('Contacts')[0].get('LastName'));
// Verify that the merge record got deleted
Account[] result = [SELECT Id, Name FROM Account WHERE Id=:mergeAcct.Id];
System.assertEquals(0, result.size());
}
}
Using the merge keyword, we merge the duplicateAccount into the masterAccount. During this operation, the duplicate account will be deleted, and its related records (like contacts) are automatically reparented to the master account.
How it works:
- We use the merge statement to combine the two accounts, keeping ‘Apex Hours’ as the master account.
- After merging, we verify that the contact has been reparented to the master account, and the duplicate account has been deleted.
Approach 2: Using the Database.merge() Method:
The Database.merge() method offers more control over the merge process, especially when handling errors. Unlike the merge statement, which throws exceptions for errors, Database.merge() returns a MergeResult object that contains success and error details, allowing for more graceful error handling.
Example: Merging Two Accounts Using Database.merge():
In this example, we’ll merge three accounts using the Database.merge() method. This example includes error handling to capture any issues without causing exceptions to halt the execution.
public class AccountMergeExample {
public static void mergeDuplicateAccounts(){
//Create master account
Account master = new Account(Name='Account1');
insert master;
// Create duplicate accounts
Account[] duplicates = new Account[]{
// Duplicate account
new Account(Name='Account1, Inc.'),
// Second duplicate account
new Account(Name='Account 1')
};
insert duplicates;
// Create child contact and associate it with first account
Contact c = new Contact(FirstName='Joe',LastName='Smith', accountId=duplicates[0].Id);
insert c;
// Merge accounts into master
Database.MergeResult[] results = Database.merge(master, duplicates, false);
for(Database.MergeResult res : results) {
if (res.isSuccess()) {
// Get the IDs of the merged records and display them
List<Id> mergedIds = res.getMergedRecordIds();
System.debug('IDs of merged records: ' + mergedIds);
// Get the ID of the reparented record and
// validate that this the contact ID.
System.debug('Reparented record ID: ' + res.getUpdatedRelatedIds());
}
else {
for(Database.Error err : res.getErrors()) {
// Write each error to the debug output
System.debug(err.getMessage());
}
}
}
}
}
How it works:
- We create a master account and two duplicates, then insert all three into the database.
- Contact is added to one of the duplicate accounts.
- We use Database.merge() to merge the accounts, and set the third parameter to FALSE to capture any errors in the MergeResult object without throwing exceptions
- If errors occur, they are captured and logged for further investigation.
Comparison: merge vs. Database.merge()
Feature | merge Statement | Database.merge() method |
Error Handling | Throws Exceptions directly | Returns errors in MergeResult. |
Use Case | Simple merges, fewer custom requirements. | More advanced error handling and control. |
Graceful Execution | Stops execution if an error accurs | Allows for error handling without stopping execution. |
Bulk operation | Can merge up to three records | Can merge up to three records |
Best Practices for Merging Records:
- Error Handling: If your use case requires custom error handling, prefer Database.merge(). Otherwise, the merge statement is a simpler option.
- Backup Your Data: Always ensure that you have proper data backups before performing merge operations.
- Test Your Merges: Use test methods to validate that your merge logic works as expected, especially in complex scenarios with multiple related records.
Merge Considerations:
- Only leads, contacts, cases, and accounts can be merged. See sObjects That Don’t Support DML Operations.
- You can pass a master record and up to two additional sObject records to a single merge method. But there is a IdeaExchange for Mass merge – ability to merge more than 3 contacts/ accounts
- Using the Apex merge operation, field values on the master record always supersede the corresponding field values on the records to be merged. To preserve a merged record field value, simply set this field value on the master sObject before performing the merge.
- External ID fields can’t be used with merge.
Conclusion:
Whether you use the simple merge statement or the more advanced Database.merge() method, Salesforce provides flexible tools for consolidating duplicate records. Both methods allow you to merge up to three records while automatically reparenting related records like contacts or opportunities.
For straightforward use cases, the merge statement works perfectly. For situations requiring more detailed error handling, Database.merge() is your go-to solution. Choose the method that best fits your business needs and implement it to keep your data clean, consistent, and efficient.
Thanks for reading, please put your questions in the comment box. 🙂