function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Rapid DevelopmentRapid Development 

SOQL in my trigger

When an opportunity is updated, I have a trigger that checks the account and contact associated with that opportunity, and updates fields on the account and contact.  To get that data, I'm using SOQL, but this causes errors when someone tries to bulk-update records.

How can I check the data from the related objects without using SOQL inside my trigger?

Here is the code I'm currently using (not the full trigger, just the beginning to show the problem area:

Thanks!
trigger SetCustomerStatusAfterOpWin on Opportunity (after insert, after update) {

    List<Contact> ContactsToUpdateListOriginal = new List<Contact>();
    List<Account> AccountsToUpdateListOriginal = new List<Account>();        
    
    for( Opportunity o : Trigger.new)
    {
        //Get contact from Opportunity
        string contactId = o.Primary_Contact__c;
        //Contact contactToUpdate = new Contact(Id = contactId);
        Contact contactToUpdate = [SELECT Id, RM_ID_Status__c, RSM_ID_Status__c, RWC_ID_Status__c
                                   FROM Contact
                                   WHERE Id = :contactId limit 1];

        //Get contacts account id
        string accountId = o.AccountId;
        //Account accountToUpdate = new Account(Id = accountId);      
        Account accountToUpdate = [SELECT Id, RM_ID_Status__c, RSM_ID_Status__c, RWC_ID_Status__c
                                   FROM Account
                                   WHERE Id = :accountId limit 1];
        //Get Opportunity's Name eg. RM-60013
        string opName = o.Name;
        
        //Update contact based on company and op status.
        if((opName.contains('RM') || opName.contains('RAMP')))
        {
           if( o.StageName == 'Closed Won')
           {
               //update contact by id
                if(contactToUpdate.Id != null)
                {
                    contactToUpdate.RM_ID_Status__c = 'Customer';
                    ContactsToUpdateListOriginal.add(contactToUpdate);
                    //update contactToUpdate;
                }
                //Update Contact's account status
                if(accountToUpdate.Id != null)
                {
                    accountToUpdate.RM_ID_Status__c = 'Customer';
                    AccountsToUpdateListOriginal.add(accountToUpdate);
                    //update accountToUpdate;         
                }
           }
           else if( o.StageName == 'Quote Sent' || o.StageName == 'Closed Lost' || o.StageName == 'Sale Pending' || o.StageName == 'Updated Quote')
           {
               //update contact by id
                if(contactToUpdate.Id != null && contactToUpdate.RM_ID_Status__c != 'Customer')
                {
                    contactToUpdate.RM_ID_Status__c = 'Quoted';
                    ContactsToUpdateListOriginal.add(contactToUpdate);
                    //update contactToUpdate;
                }
                //Update Contact's account status
                if(accountToUpdate.Id != null && accountToUpdate.RM_ID_Status__c != 'Customer')
                {
                    accountToUpdate.RM_ID_Status__c = 'Quoted';
                    AccountsToUpdateListOriginal.add(accountToUpdate);
                    //update accountToUpdate;         
                }
           }
            
        }// end if

 
Best Answer chosen by Rapid Development
Mathew Andresen 5Mathew Andresen 5
It looks to me like you are iterating the query over in the for loop.  This will make you run into query limits.  Instead you should do the query for the whole trigger set.
 
FROM Contact WHERE Id IN :Trigger.new

See the trailhead example here
https://developer.salesforce.com/trailhead/force_com_programmatic_beginner/apex_triggers/apex_triggers_bulk

Thanks,

All Answers

Mathew Andresen 5Mathew Andresen 5
It looks to me like you are iterating the query over in the for loop.  This will make you run into query limits.  Instead you should do the query for the whole trigger set.
 
FROM Contact WHERE Id IN :Trigger.new

See the trailhead example here
https://developer.salesforce.com/trailhead/force_com_programmatic_beginner/apex_triggers/apex_triggers_bulk

Thanks,
This was selected as the best answer
Rapid DevelopmentRapid Development
Thanks Mathew, I'm new to the world of triggers, you're link was exactly what I needed. 
Mathew Andresen 5Mathew Andresen 5
You're welcome.  I'm new to this as well.  I've found the trailheads to be very good reading.  I also am finding the tutorials over ad sfdc99 to be very good

http://www.sfdc99.com/beginner-tutorials/
 
Chander GhorelaChander Ghorela
@Methew, even sfdc99 is doing query in for loop in trigger
https://www.sfdc99.com/2013/10/19/example-how-to-write-a-deduping-trigger-for-leads-and-contacts/