As far as I know, you can't find out which records in a trigger have failed from within that same trigger.
If you have some apex code which contains a DML operation, or if your trigger itself contains a DML operation, you can make use of the System.Database
methods Database.insert()
, Database.update()
, Database.delete()
and the like.
Here's a link to the System.Database documentation
These methods return a Database.SaveResult[]
, which you can loop through, and determine whether a record was saved successfully or not.
The code to make use of this looks something like this
// Assuming that you have some list of sObjects, initialized and populated elsewhere in your code, called sObjectsToUpdate.
List<Id> successes = new List<Id>();
for(Database.SaveResult sr : Database.update(sObjectsToUpdate, false)){
if(sr.isSuccess()){
successes.add(sr.getId());
}
}
The second parameter of the database save methods (well, the ones where a List is the first parameter) is a Boolean called allOrNone
. For detecting successes, it's vital to pass false
. Passing false means that all records will be attempted to be saved, and successfully saved records won't get rolled back if one (or more) other records fail to save.
Getting a list of failures, for those interested, is a bit more involved, as Database.SaveResult.getId()
returns null for records that failed. This is something I was running into quite recently, and this question has two good answers
The gist of the solution for that question is that the order of the Database.SaveResult
list will be the same as the order of the list that was passed into the database save method. Keeping track of the list index allows you to tie the two lists together.
Reproducing the code from the accepted answer on that question
List<Account> accountsList = [select Id from Account];
for(Account a : accountsList) {
a.Name = 'Test',
}
List<Database.SaveResult> res = Database.update(accountsList, false);
//for (Database.SaveResult s : res) { //replaced by the following line
for (Integer i = 0; i < accountsList.size(); i++) {
Database.SaveResult s = res[i];
Account origRecord = accountsList[i];
if (!s.isSuccess()) {
system.debug(s.getId()); // I get null here
system.debug(origRecord.Id); //This should be the Id you're looking for
}
}