Newer Version Available
Merging Records
Use the merge Statement
This example shows how to merge a duplicate account record into a main account record. The duplicate account has a related contact, which is moved to the main account record after the merge operation. After merging, the duplicate record is deleted and only the main record remains in the database.
1// Insert new accounts
2List<Account> ls = new List<Account>{
3 new Account(name='Acme Inc.'),
4 new Account(name='Acme')
5 };
6insert ls;
7
8// Queries to get the inserted accounts
9Account mainAcct = [SELECT Id, Name FROM Account WHERE Name = 'Acme Inc.' LIMIT 1];
10Account dupAcct = [SELECT Id, Name FROM Account WHERE Name = 'Acme' LIMIT 1];
11
12// Add a contact to the account to be merged
13Contact c = new Contact(FirstName='Joe',LastName='Merged');
14c.AccountId = dupAcct.Id;
15insert c;
16
17try {
18 merge mainAcct dupAcct;
19} catch (DmlException e) {
20 // Process exception
21 System.debug('An unexpected error has occurred: ' + e.getMessage());
22}
23
24// After the account is merged with the main account,
25// the related contact is moved to the main record.
26mainAcct = [SELECT Id, Name, (SELECT FirstName,LastName From Contacts)
27 FROM Account WHERE Name = 'Acme Inc.' LIMIT 1];
28System.assert(mainAcct.getSObjects('Contacts').size() > 0);
29System.assertEquals('Joe', mainAcct.getSObjects('Contacts')[0].get('FirstName'));
30System.assertEquals('Merged', mainAcct.getSObjects('Contacts')[0].get('LastName'));
31
32// Verify that the duplicate record is deleted
33Account[] result = [SELECT Id, Name FROM Account WHERE Id=:dupAcct.Id];
34System.assertEquals(0, result.size());Use the Database.merge Method
This second example is similar to the previous example, except that it uses the Database.merge method instead of the merge statement. The last argument of Database.merge is set to false, so any errors encountered in this operation are returned in the merge result without throwing exceptions. In the example, a main account and two duplicate account records are created. One of the duplicate account records has a child contact record. Through the merge operation, the contact is moved to the main account record, and the other records are deleted.
1// Create main account
2Account main = new Account(Name='Account1');
3insert main;
4
5// Create duplicate accounts
6Account[] duplicates = new Account[]{
7 // Duplicate account
8 new Account(Name='Account1, Inc.'),
9 // Second duplicate account
10 new Account(Name='Account 1')
11};
12insert duplicates;
13
14// Create child contact and associate it with first account
15Contact c = new Contact(firstname='Joe',lastname='Smith', accountId=duplicates[0].Id);
16insert c;
17
18
19
20// Get the account contact relation ID, which is created when a contact is created on "Account1, Inc."
21AccountContactRelation resultAcrel = [SELECT Id FROM AccountContactRelation WHERE ContactId=:c.Id LIMIT 1];
22
23
24// Merge duplicate accounts into main account
25Database.MergeResult[] results = Database.merge(main, duplicates, false);
26
27for(Database.MergeResult res : results) {
28 if (res.isSuccess()) {
29 // Get the main record ID from the result and validate it
30 System.debug('Main record ID: ' + res.getId());
31 System.assertEquals(main.Id, res.getId());
32
33 // Get the IDs of the merged records and display them
34 List<Id> mergedIds = res.getMergedRecordIds();
35 System.debug('IDs of merged records: ' + mergedIds);
36
37 // Get the ID of the reparented record and
38 // validate that this the contact ID.
39 System.debug('Reparented record ID: ' + res.getUpdatedRelatedIds());
40
41 // Make sure there are two IDs (contact ID and account contact relation ID); the order isn't defined
42 System.assertEquals(2, res.getUpdatedRelatedIds().size() );
43 boolean flag1 = false;
44 boolean flag2 = false;
45
46
47 // Because the order of the IDs isn't defined, the ID can be at index 0 or 1 of the array
48 if (resultAcrel.id == res.getUpdatedRelatedIds()[0] || resultAcrel.id == res.getUpdatedRelatedIds()[1] )
49 flag1 = true;
50
51 if (c.id == res.getUpdatedRelatedIds()[0] || c.id == res.getUpdatedRelatedIds()[1] )
52 flag2 = true;
53
54 System.assertEquals(flag1, true);
55 System.assertEquals(flag2, true);
56
57 }
58 else {
59 for(Database.Error err : res.getErrors()) {
60 // Write each error to the debug output
61 System.debug(err.getMessage());
62 }
63 }
64}Merge Considerations
When merging sObject records, consider these rules and guidelines:
- Only leads, contacts, cases, and accounts can be merged. See sObjects That Don’t Support DML Operations.
- You can pass a main record and up to two additional sObject records to a single merge method.
- Field values on the main record, including null and empty field values, always supersede the corresponding field values on the records to be merged. Therefore, if a field value on the main record is empty, the resulting field value remains empty after the merge operation regardless of the field value on the duplicate record. To preserve a field value from a duplicate record, manually set this field value on the main record before performing the merge.
- External ID fields can’t be used with merge.