ApexSensei

Drills › Query the org (SOQL)

Read a Contact's Account

Query the org (SOQL) · Intermediate · 14 min · Runs in your Salesforce Developer org · Apex Path

Scenario. A Contact export needs the parent Account name but must also survive Contacts that are not linked.

Read Account.Name through each tagged Contact, and use it safely for a Contact that has no Account.

What you will learn

A child-to-parent query uses dot notation. From Contact, select Account.Name, then read it from each row.

for (Contact row : [SELECT Id, Account.Name FROM Contact]) {
    String parentName = row.Account?.Name;
}

?. is safe navigation: it gives null when row.Account is null.

Gotcha. Reading row.Account.Name on a Contact with no Account returns null without throwing — but calling .toUpperCase() on that null does throw. Check for null first.

The task

Query three tagged Contacts, read each one's Account name through the relationship, and upper-case it without crashing on the Contact that has no Account.

Examples:

  • two Contacts with an AccountId → Contacts with an Account: 2
  • both upper-cased parent names equal the seeded Account's upper-cased Name → Parent names match: true
  • one Contact with no Account → Contacts without an Account: 1 and Orphan parent name: null, with no error

Requirements:

  1. Query Contacts with LastName LIKE :contactPattern, and select Account.Name.
  2. Loop over the rows. Read the parent name with row.Account?.Name. Reading it never throws. For the Contact with no Account you get null.
  3. When the parent name is not null, upper-case it with toUpperCase() and compare it with parent.Name.toUpperCase(). That call is what throws on a null. Start parentNamesMatch as true before the loop and set it to false when a name differs.
  4. Count Contacts with and without an Account. For the Contact with no Account, store its parent name (null) in orphanParentName.
  5. Print Contacts with an Account:, Parent names match:, Contacts without an Account: and Orphan parent name:.

Starter code

String tag = 'AS-Q306-' + UserInfo.getUserId() + '-' +
    String.valueOf(Datetime.now().getTime());
Account parent = new Account(Name = tag);
insert parent;
List<Contact> seeded = new List<Contact>{
    new Contact(LastName = tag + '-LinkedA', AccountId = parent.Id),
    new Contact(LastName = tag + '-LinkedB', AccountId = parent.Id),
    new Contact(LastName = tag + '-Orphan')
};
insert seeded;
String contactPattern = tag + '-%';

Integer linkedCount = 0;
Integer orphanCount = 0;
Boolean parentNamesMatch = true;
String orphanParentName = 'unknown';
System.debug('Contacts with an Account: ' + linkedCount);
System.debug('Parent names match: ' + parentNamesMatch);
System.debug('Contacts without an Account: ' + orphanCount);
System.debug('Orphan parent name: ' + orphanParentName);

When it passes

Two Contacts read and upper-case the seeded Account's Name, and the Contact with no Account is counted and reported as null without an error.

Try this drill free

You write the Apex yourself. ApexSensei runs it and tells you what passed and what did not.

‹ Find missing Contact emails · Load Account Contacts ›