You get the best of both worlds
Chill it out, take it slow
Then you rock out the show
You get the best of both worlds
Mix it all together
And you know that it's the best of both worlds
The best of both worlds, yeah
Hannah Montana would have CLEARLY been a fan of upsert
DML statements. An upsert allows you to either insert or update a sObject in just one call.
Internally, the operation looks to see if it can find a sObject record with the same Id. If it does, it will update the record. Otherwise, it'll insert the record. There are some exceptions listed here.
Let's use this operation to solve the issue we saw in the last lesson.
List<Account> accountsWithoutType = [SELECT Id, Name, Type FROM Account WHERE Type = '']; for (Account acc : accountsWithoutType) { acc.Description = 'Basic'; } Account newAcc = new Account(Name = 'Apple', Type='Basic'); accountsWithoutType.add(newAcc); update accountsWithoutType; // This threw an Exception
Changing update
to upsert
will allow the accounts from the SOQL query to be updated and the newAcc
we created in memory to be created. Simple change update
to upsert
:
List<Account> accountsWithoutType = [SELECT Id, Name, Type FROM Account WHERE Type = '']; for (Account acc : accountsWithoutType) { acc.Description = 'Basic'; } Account newAcc = new Account(Name = 'Apple', Type='Basic'); accountsWithoutType.add(newAcc); upsert accountsWithoutType; // Hannah would be pleased
The linked article explains that the Id
field of a sObject record is used by default to match the sObject with existing records. This matching process determines whether the sObject should be inserted as a new record or updated as an existing one.
You can specify a different field for matching, such as an ExternalId field or the Email field, on certain standard sObjects like Email or Contact.
To do this, you'll pass in the field token:
List<Contact> reconciliationContacts = new List<Contact>(); // Logic for retrieving & setting this list omitted. Imagine something like the above Account logic happens. upsert reconciliationContacts Contact.Fields.Email;
If you choose to do this, the field used as the matcher must be set on the upserted record. If not, you'll face another DML exception, like this: MISSING_ARGUMENT, Email not specified: []
.