Kelly
Kelly

Reputation: 111

Why am i getting DML error in Salesforce update trigger?

Im trying to update BilingCountry in Salesforce via the Bulk API from a csv, there are 1025 entries in the csv file. The Account ids in the csv have a BillingCountry different to what is in Salesforce but i get the following error:

CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY:test_tr_U: System.LimitException: Too many DML rows: 10001:--

Here is my Trigger:

   Trigger test_tr_U on Account (after update)
   {
    if(checkRecursion.runOnce())
    {
        set<ID> ids = Trigger.newMap.keyset();
        List<TestCust__c> list1 = new List<TestCust__c>();
        for(ID id : ids)
        {
            for (Account c: Trigger.new)
            {
                Account oldObject = Trigger.oldMap.get(c.ID);
                if (c.Billing_Country__c!= oldObject.Billing_Country__c || 
                  c.BillingCountry!= oldObject.BillingCountry )
                {
                    TestCust__c change = new TestCust__c();
                    change.Field1__c = 'update'; 
                    change.Field2__c = id; 
                    change.Field3__c = false; 
                    change.Field4__c = 'TESTCHANGE'; 
                    list1.add(change);
                }
            }
        }
        Database.DMLOptions dmo = new Database.DMLOptions();
        dmo.assignmentRuleHeader.useDefaultRule = true;
        Database.insert(list1, dmo);
    }
  }

Upvotes: 0

Views: 437

Answers (1)

RubenDG
RubenDG

Reputation: 1405

Looping over every id then over every updated account will result in the creation of #id * #account. Those are the same value so you'll create #account^2 (1050625) TestCust__c records.
Salesforce splits the 1025 records in chunk of 200 records and since a Bulk API request caused the trigger to fire multiple governor limits are reset between these trigger invocations for the same HTTP request.
Anyway for each trigger run you're creating 200*200 = 40000 TestCust__c records, which are highly above the limit of 10000 records per transaction, therefore the system will raise LimitException.

You should remove the outer loop: it's simply wrong.

Trigger test_tr_U on Account (after update)
{
    if(checkRecursion.runOnce())
    {
        List<TestCust__c> list1 = new List<TestCust__c>();
        for (Account c: Trigger.new)
        {
            Account oldObject = Trigger.oldMap.get(c.Id);
            if (c.Billing_Country__c != oldObject.Billing_Country__c || 
                c.BillingCountry!= oldObject.BillingCountry)
            {
                TestCust__c change = new TestCust__c();
                change.Field1__c = 'update'; 
                change.Field2__c = c.Id; 
                change.Field3__c = false; 
                change.Field4__c = 'TESTCHANGE'; 
                list1.add(change);
            }
        }
        Database.DMLOptions dmo = new Database.DMLOptions();
        dmo.assignmentRuleHeader.useDefaultRule = true;
        Database.insert(list1, dmo);
    }
}

Upvotes: 1

Related Questions