Navigating Relationships…..

Navigating relationships in life may be hard but doesn't have to between custom sObjects :) . The SOQL documentation  has several examples with standard sObjects. Custom sObjects have some differences – mostly syntactical.  We will illustrate that using a few sample SOQL queries.

We will use the example from the Developer Guide The object model is reproduced below (click on the pictures to enlarge them).

M1When you insert a relationship field on an sObject (either a lookup or master-detail) to another object, the other object is called the parent sObject.  So Location is the parent of Position in the object model shown.  The cardinality from parent to child is one to many, so a single location can have many positions associated with it.  The child object will have both the ID of the related parent record as well as a relationship field to access the fields in the related record.  


CHILD to PARENT

Say we want to find the location id and city associated with a given position.  The query would look like this

SELECT Location__r.Id, Location__r.City__c FROM Position__c p WHERE p.Name='POS-00001'

What is Location__r?  It is the name of the relationship field from Position to Location.  You can find this on the field definition screen – click on the picture on the left.  Note that you have to append a __r to the name on the screen. You can traverse multiple levels of child parent relationship in this manner.  For example, we can retrieve the field values of a location record from Job Application by traversing from Job Application to  Position to Location as shown below.M2

SELECT Position__r.Location__r.Id, Position__r.Location__r.City__c  FROM Job_Application__c ja WHERE ja.Name = 'JA-00001'



PARENT to CHILD

Remember that the cardinality of this relationship is one to many so we should expect to retrieve back a collection of child objects.  The child objects are retrieved using a sub-query.

Location__c[] locations = [SELECT  l.Name, l.City__c, (SELECT Name, Department__c FROM Positions__r) FROM Location__c l ]

Positions__r is the name of the child relationship.  We find it on the field definition screen as before – click on the picture to the right.  Notice the plural (by default) and appending __r (as before). 
Now we can iterate over the collection of locations as well as the associated child positions for each location in a loop.

for( Location__c l : locations ){ // position object associated with each location for( Position__c p : l.positions__r){ System.debug('*****>>>>>> Name = ' +p.Name +' Department = ' +p.Department__c ) ;  }} M3 

The previous query did an outer join, so it would retrieve locations even if there were no associated positions. To only retrieve locations for which there are associated positions, we would need to do a semi-join as shown below.

Location__c[] locations = [SELECT Id, Name, City__c, (SELECT Id, Name, Department__c FROM Positions__r) FROM Location__c WHERE Id IN (SELECT Location__c from Position__c) ] ;

CHANGING THE ASSOCIATED RECORD 

Notice the query after IN in the previous example. Location__c contains the ID of the related Location record. We can use this field to change the related record as in the example below.

// Retrieve a position record with the ID of the associated location recordPosition__c p = [SELECT Location__c, Location__r.Name FROM Position__c                 WHERE Location__r.Name='HQ' LIMIT 1]// Retrieve the Id of the record we want to point it toLocation__c loc = [ select Id from Location__c where Name='Reston' ] ;//change it and update the databasep.location__c = loc.Id ;update p ;The position now points to the Reston location.




tagged , Bookmark the permalink. Trackbacks are closed, but you can post a comment.
  • Sean Harrison

    maybe it’s just my Chrome and Firefox browsers but the code example in Parent-to-Child starting “for( Location__c l : locations )” doesn’t wrap so everything after “Position__c p : l.” is cut off