27

I am using Database.SaveResult and Database.update(..., false) for the very first time and ask myself how to get the Id of the record where a dml has failed.

I expected Database.SaveResult.getId()` to give me that answer but NO...it is empty when the dml failed.

Help ;-)!

4 Answers 4

47

We can use List index Property to get the Id of the failed record .The Index of the List which we are updating and also the result set retrieved has the same index .Using the above property for our advantage we can draft a pseduo code as below

List<Database.SaveResult> updateResults = Database.upsert(arudate, false);
for(Integer i=0;i<updateResults.size();i++){
    if (updateResults.get(i).isSuccess()){
        updateResults.get(i).getId();

    }else if (!updateResults.get(i).isSuccess()){
        // DML operation failed
        Database.Error error = updateResults.get(i).getErrors().get(0);
        String failedDML = error.getMessage();
        arudate.get(i);//failed record from the list
        system.debug('Failed ID'+arudate.get(i).Id);
     }

}
4
  • 2
    does anyone understand why the failed ones don't include the ID?
    – Phil B
    Oct 5, 2015 at 21:09
  • 7
    because salesforce failed to properly implement the function
    – NSjonas
    Apr 5, 2017 at 3:54
  • thanks it works, and if you have Map can use same principle, but you just need convert map into list "accMap.values().get(i).Id;"
    – Radamanf
    Jun 20, 2018 at 9:35
  • Would you please post a link to the official documentation that mentions this? Thanks!
    – Bahman.A
    Feb 18, 2021 at 23:54
2

Use an integer as a counter and get the relevant record from the list.

Database.SaveResult[] srList = Database.update(updlist,false);
    Integer i=0;
    for (Database.SaveResult sr : srList) {
        if (!sr.isSuccess()) {
            for(Database.Error err : sr.getErrors()) { 
                System.debug(updlist.get(i).Id + ': ' + err.getMessage());
            }
        }
        i++;
    }  
}
0

Depending on the situation, if possible I usually use the following method for my DML error handling.

public static void dmlErrorHandling(List<Database.SaveResult> srList, List<Contact> contactList, String additionalMessage)
{
    List<Id> successIds = new List<Id>();
    
    for (Database.SaveResult sr : srList)
    {
        if (sr.isSuccess()) { successIds.add(sr.getId()); }
    }
    
    if (successIds.size() != contactList.size())
    {
        for (Contact c : contactList)
        {
            if (!successIds.contains(c.Id))
            {
                // Handle the error, Note that you have access to the failed record
                System.debug('DML failed for Contact with ID: '+ c.Id);            
            }
        }
    }
}

Just to clarify the logic here: You loop over the List of Database.SaveResult and add all the IDs of the records that didn't fail during DML, to a List of IDs. Then you loop over the initial List of records that you passed to the DML method (Insert/Update) and for each record ID you check to make sure it exists in the list of success IDs and if doesn't, there you have a record with failed DML and you can do whatever you'd like to from this point with the failed records.

1
  • 2
    a more efficient pattern is to have a Map<Id,Contact> contactsById and then look up the contact using sr.getId()
    – cropredy
    Jul 1, 2020 at 22:11
-1

Really old question.. but if anyone stumbles across it...

A way to do this is loop back over the records that were passed to the call to Database.insert. The ones that succeeded will have an ID, those that failed with still have an ID = null.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .