+ Start a Discussion
SteveOrgSteveOrg 

List has no rows for assignment to SObject

Hi there, when I test my trigger by updating an opportunity to be 'closed won', I am getting an error back specifying that my trigger isn't returning any rows.  I'm hoping there is something quick that I missed:

 

Error:

 

Error: Invalid Data. 
Review all error messages below to correct your data.
Apex trigger updateOpptyCustomerWons caused an unexpected exception, contact your administrator: updateOpptyCustomerWons: execution of AfterUpdate caused by: System.QueryException: List has no rows for assignment to SObject: Trigger.updateOpptyCustomerWons: line 24, column 1

 

Trigger:

 

trigger updateOpptyCustomerWons on Opportunity (after update) { 

    //make a set to hold opportunity ids that we need
    Set<Id> opptyIds = new Set<Id>();
    
    for(Opportunity o : trigger.new)
        {
        //check to see if our field has been changed
        if(o.StageName != trigger.oldMap.get(o.Id).StageName){
            
            opptyIds.add(o.Id);
            
        }

       }
    
    if(!opptyIds.isEmpty()){
    
        
        //Opportunity opp
        
        
        Opportunity oppty = [SELECT Id,StageName FROM Opportunity WHERE StageName = 'Closed Won' AND Id IN :opptyIds limit 1];
        
        Opportunity opp = new Opportunity();
        
        if (oppty != null) {
        string s = oppty.name;
        OpportunityUpdateURL.hitTheServer(s);
        }    
        
      
       
    }


}

 

Best Answer chosen by Admin (Salesforce Developers) 
ashishkrashishkr

The "limit 1" can be tricky. Remove it and use a List<Opportunity> to receive the result of soql. Also, since you need the Name of opportunity, include it in the SOQL.

 

trigger updateOpptyCustomerWons on Opportunity (after update) { 

    //make a set to hold opportunity ids that we need
    Set<Id> opptyIds = new Set<Id>();
    
    for(Opportunity o : trigger.new)
        {
        //check to see if our field has been changed
        if(o.StageName != trigger.oldMap.get(o.Id).StageName){
            
            opptyIds.add(o.Id);
            
        }

       }
    
    if(!opptyIds.isEmpty()){
    
        
        //Opportunity opp
        
        
      List<Opportunity> opptyList = [SELECT Id,StageName,Name FROM Opportunity WHERE StageName = 'Closed Won' AND Id IN :opptyIds ]; //include Name
        for(Opportunity oppty: opptyList){
        Opportunity opp = new Opportunity();
        
        //null check is not required.
        string s = oppty.name;
        OpportunityUpdateURL.hitTheServer(s);
           
        
      }
       
    }


}

 

All Answers

ashishkrashishkr

The "limit 1" can be tricky. Remove it and use a List<Opportunity> to receive the result of soql. Also, since you need the Name of opportunity, include it in the SOQL.

 

trigger updateOpptyCustomerWons on Opportunity (after update) { 

    //make a set to hold opportunity ids that we need
    Set<Id> opptyIds = new Set<Id>();
    
    for(Opportunity o : trigger.new)
        {
        //check to see if our field has been changed
        if(o.StageName != trigger.oldMap.get(o.Id).StageName){
            
            opptyIds.add(o.Id);
            
        }

       }
    
    if(!opptyIds.isEmpty()){
    
        
        //Opportunity opp
        
        
      List<Opportunity> opptyList = [SELECT Id,StageName,Name FROM Opportunity WHERE StageName = 'Closed Won' AND Id IN :opptyIds ]; //include Name
        for(Opportunity oppty: opptyList){
        Opportunity opp = new Opportunity();
        
        //null check is not required.
        string s = oppty.name;
        OpportunityUpdateURL.hitTheServer(s);
           
        
      }
       
    }


}

 

This was selected as the best answer
SteveOrgSteveOrg

Hi Thanks for your reply.

 

When I return a list of opportunities then I receive the following compile error:

 

Error: Compile Error: Initial term of field expression must be a concrete SObject: LIST<Opportunity> at line 32 column 20

 

My trigger passes values to a class within a future method, which will break if my results are a list.  I only need to return the single record that was updated in this example, so I was hoping I didn't need to produce an array.

SteveOrgSteveOrg

Hi there, disregard my previous message, Your solition worked for me.  Thanks so much!!!