[SalesForce] How to access trigger.oldmap outside the for loop

When I update records in SFDC using dataloader, it executes my trigger and I'm getting a System.LimitException: Too many SOQL queries: 101. I am now changing my trigger so that I don't make any SOQL calls in the FOR loop. Problem is, how can I get the oldMap and NewMap of the Opportunity outside the for loop? Because the for loop is creating the variable "opp" which I need to reference to get the old map. How can i do this outside the for loop? I've tried looking for syntax but haven't found anything. Thanks in advance for the help.

trigger TestTrigger on Opportunity (before update) {
    Opportunity oldOpportunity = Trigger.oldMap.get(opp.ID);
    for(Opportunity opp : Trigger.new){
       ...
       oppOwnerId = [SELECT Id FROM User WHERE Id=:oldOpportunity.OwnerId limit 1];
       ...
    }
}

Best Answer

To access a Map (as in oldMap), you will need to access by Id. If it is just the old Opportunity Owner ID you are after, you can simply access it as - no need to perform the query:

trigger TestTrigger on Opportunity (before update) {
    for(Opportunity opp : Trigger.new){
       Opportunity oldOpportunity = Trigger.oldMap.get(opp.ID);
       oppOwnerId = oldOpportunity.OwnerId;
       ...
    }
}

However, i suspect you are not and that you do need to perform the query to retrieve some other information, in which case you are thinking about this the wrong way. You need to 'bulkify' your Trigger.

What you will have to do instead of what you are suggesting is refactor your trigger a little. You should first collect a set of OwnerIds from the 'old' collection, for example:

Set<Id> ownerIds = new Set<Id>();
for( Opportunity opp : Trigger.old ) {
    ownerIds.add( opp.OwnerId );
}

Then, using that set, you should query all of the Users outside of the loop (i.e. once for all the OwnerIds) and create a Map for easy access, for example:

Map<Id,User>  userMap = new Map<Id,User> ( [ Select Id From user Where Id IN ownerIds ] );

Then, from within the Loop, you can access the User as you wish using the map:

for( Opportunity opp : Trigger.new ) {
    User oppOwnerId = userMap.get( Trigger.oldMap.get( opp.Id ).OwnerId );
}

This is a rather futile example because the code is only returning the User Id which you essentially have already anyway (in the oldMap).

Related Topic