3

I have some accounts to update but some validation rules can failed.

So to avoid this I use the Database.update() function to update accounts even if some DML exception occur.

try {
    List<Account> accounts = [select Id from Account];

    for(Account acc : accounts) {
        acc.Name= 'test';
    }

    system.debug('one');

    List<Database.SaveResult> result = Database.update(accounts, false);

    system.debug('two');
} catch(Exception e) {
    String txt = e.getMessage();
    system.debug(txt);
}

But only the first log is displayed. I don't have the second one and I don't reach the catch block. I can see that some validation rules fail on some account names.

Do you know what happens ? If a DML exception occurs on a Database.update() what happens ?

4
  • Does the debug log show the update executing? as for the debug, are your log levels set to "Debug" or higher? Did you check the DB to see if the results were actually updated? Any errors thrown?
    – Eric
    Commented Oct 28, 2014 at 10:43
  • Yes I see a line with one debug log only. And then, I have an afterUpdate trigger and that's at this moment I see the validation rules error in the log. And yes, I can see some accounts well-updated. So I think the update works well but i don't know why I can't do some stuff after it !
    – SF_user
    Commented Oct 28, 2014 at 10:48
  • Which debug statement is not executing? system.debug('two') or system.debug(txt). If it is the first, that is extremely puzzling. If it is the second it is because by using the false parameter you are preventing any exceptions from being thrown, and you must loop through the Database.SaveResult list to inspect for failures as I showed in my answer below. In your debug log, filter on USER_DEBUG (case sensitive) and verify that you are not getting the debug.
    – pchittum
    Commented Oct 28, 2014 at 11:42
  • system.debug('two') is not executed. Puzzling, yeah like you said !
    – SF_user
    Commented Oct 28, 2014 at 11:50

2 Answers 2

8

The reason your catch block is not being executed is because of the false parameter you are passing in:

Database.update(accounts, false);

That parameter is called is_all_or_none meaning treat the transaction atomically. If something fails, then make the entire transation fail. The reason for atomicity is pretty standard here...if one of my records fails to save, if an error occurs, I want to ensure that everything I attempted will roll back, preventing data from being out of sync.

When you set this to false, what that means is that if one record has an exception, validation rule failure (which actually is just a thrown exception), Trigger validation failure (myObje.addError(...) which also is just a thrown exception) that one record will fail to save, but any other records in the batch will complete just fine.

In your dexcription, you write:

So to avoid this I use the Database.update() function to update accounts even if some DML exception occur.

This is a misunderstanding of the purpose as you can hopefully now see. Using Database.update isn't a way to bypass validation rules. It is a way to prevent one validation rule failure from causing many good records from failing.

To get your save to work, you need to understand what your validation rule failure is, and then attempt to save data that meets the validation criteria that have been set in your system. You could also evaluate whether this validation rule is actually meaningful anymore and make a choice to remove it, but I would not recommend this without thoughtful review, and checking with others who are using your org.

As to why the second System.debug() is not being called (system.debug('two')) that is extremely puzzling. Are you certain it is not?

Finally, when you use the is_all_or_none=false version of DML (it also exists for insert, upsert, delete, and undelete), the way you look for failed records is as follows:

List<Database.SaveResult> results = Database.update(accounts, false);
for (Database.SaveResult result : results) {
  if (!result.isSuccess()){
    for (Database.Error err : result.getErrors()){
      System.debug('Error: '+ err.getStatusCode() + ' ' + err.getMessage());
    }
  }
}
2
  • Thanks Peter for your answer. That was I did but the process on the errors doesn't work. So I decided to add a system.debug() to ensure everything is good. And it's at this moment I saw that I don't reach the code after the update ! And I can't understand why.
    – SF_user
    Commented Oct 28, 2014 at 10:13
  • Try dropping the try/catch and instead loop through the results as I showed.
    – pchittum
    Commented Oct 28, 2014 at 11:43
1

Using Database.update(accounts, false); will not throw any error because you have set DMLOption optAllOrNone equal to false. It means successfully processed records are committed while records with errors aren't. And no error displayed.

6
  • Ok, so I can check which one failed immediatly after the update and no in the catch block ?
    – SF_user
    Commented Oct 28, 2014 at 10:04
  • Database class methods return Database.SaveResult instance. You can use it. @SF_user
    – Ashwani
    Commented Oct 28, 2014 at 10:24
  • Yes, as I said to Peter, that what I used. But it didn't work. So to see if everything works well, I added a system.debug(). And I saw that I never reach this code and I try to understand why ! Thanks for your help.
    – SF_user
    Commented Oct 28, 2014 at 10:30
  • @SF_user You are unable to see ` system.debug('two');` ?
    – Ashwani
    Commented Oct 28, 2014 at 10:47
  • No, only the first log, then the update process and that's all ! Nothing concerning the second log.
    – SF_user
    Commented Oct 28, 2014 at 10:50

You must log in to answer this question.

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