0

Will acc.Contacts return all the related contacts to the Account? What does actually acc.Contacts means in this code? When I am doing System.debug() it returns (). What should be the output for this code?

**Note:**This account has two related contacts in the org.

Account acc = [SELECT ID,NAME FROM ACCOUNT WHERE NAME = 'abc2'];
List<Contact> con = acc.Contacts;
System.debug('Contacts:' + con);

enter image description here

5

Given the code you have, no, acc.Contacts will not return any Contacts.

To get related Contacts, you need to query for them. Since you haven't queried for them, you get an empty list (honestly, I'm a little surprised that you didn't get an error about "SObject row was retrieved via SOQL without querying the requested field").

You can use an inner query to get child records (we can only query down a maximum of 1 level in a hierarchy, from parent to child), provided you have access to the object and know the child relationship name.

[SELECT Id, Name, (SELECT Id, Name FROM Contacts) FROM Account]

"Contacts" is the child relationship name here. The plural of the object name is the normal child relationship name for standard relationships. For custom relationships, it's typically plural + __r (e.g. if the child object API name is MyCustomObject__c, the usual child relationship name would be MyCustomObjects__r)

When you query for data on a parent record (let's use Account's ParentId relationship field), that data is stored in an embedded SObject instance. If you query the parent name, you access that data with acc.Parent.Name. acc.Parent is a fully-fledged SObject embedded into the child Account record. You're accessing the parent record, and then accessing the name.

A similar thing happens with queried child records, except instead of a single embedded SObject record you get an embedded List<SObject>. You access data from that the same way you would access data from any other list (loop over it, or index into it).

1
  • 1
    The "requested field" error only counts for fields. Child relationships are always safe, non-null lists. Try this out: Contact[] c = new Account().Contacts; System.debug(c.size()); Parent relationships don't throw NullPointerException when they're null, try: System.debug(new Contact().Account.Name); (but, be aware that trying to call a method on Name from here would throw a NullPointerException).
    – sfdcfox
    Jan 9 at 15:40
3

acc.Contacts will return all Contacts related to the Account if you query for them first.

(That is assuming that there are Contacts associated to the Account - if there are no related Contacts, then obviously any attempt to query for them or reference them will not show anything.)

If you change your first line to:

Account acc = [SELECT ID, NAME, (SELECT Id FROM Contacts) FROM ACCOUNT WHERE NAME = 'abc2'];

Then your System.debug() line should show you some Contact details.


NOTE

If you want to reference any specific fields other than Id in those Contacts, you will need to include those fields in your query, or else you will receive an error (You can see my answer to this recent question for more details.)

For example, using the above query, if you later tried this...

for (Contact c : con) {
    System.debug(c.LastName);
}

...you would get the error mentioned the above referenced question.

But if you changed your query to...

Account acc = [SELECT ID, NAME, (SELECT Id, LastName FROM Contacts) FROM ACCOUNT WHERE NAME = 'abc2'];

...then the above for loop would work.


Another way to approach your original inquiry would be to do this:

Account acc = [SELECT ID,NAME FROM ACCOUNT WHERE NAME = 'abc2'];
List<Contact> con = [SELECT Id FROM Contact WHERE AccountId = :acc.Id];
System.debug('Contacts:' + con);

But that counts as another query toward your SOQL limit, so if that is an issue with your overall class/method code, that should be considered.


One issue with your original query is if there is more than one Account that has the Name of "abc2", then you will get a different error. This is because queries actually return a List of records and you would be trying to set a single record variable to equal a List of records. In the case where there is exactly one record returned, it works; but instead of assuming/hoping/praying that it always works that way, you should do one of two options - depending on what your ultimate goal is and whether you care which record is returned if there is more than one that matches your query:

Option 1

Account acc = [SELECT ID,NAME FROM ACCOUNT WHERE NAME = 'abc2' LIMIT 1];

The LIMIT 1 does just that - limits the query to return only one record. But you can't pick which record is returned if there is more than one. So if it matters which record is returned, you can either make your query more specific (but you should still leave the LIMIT 1 because - trust me - that will keep you having debug nightmares in the future), or you go with:

Option 2

List<Account> accs = [SELECT ID,NAME FROM ACCOUNT WHERE NAME = 'abc2'];

Then use a for loop or some other means to iterate through that List - even if it contains only one record.


Further reading:

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.