Salesforce Object Query Language (SOQL) is used to read records from Salesforce objects. SOQL syntax looks similar to SQL, but it is built for Salesforce object API names, field API names, and object relationships. In Apex, a SOQL query is usually written inline inside square brackets.

This updated tutorial explains the required parts of Apex SOQL syntax, the optional clauses used most often, and practical examples for WHERE, IN, bind variables, sorting, limits, and relationship queries.

SOQL Syntax

</>
Copy
SELECT fields 
FROM Object 
WHERE Condition 
Ordering LIMIT
FOR VIEW Or FOR REFERENCE
OFFSET 
UPDATE VIEWSTAT

From the above SOQL syntax we have many things to observe and understand. SELECT, fields, FROM, and Object are required in a normal SOQL query. Clauses such as WHERE, ORDER BY, LIMIT, OFFSET, FOR VIEW, and FOR REFERENCE are optional and are added only when the query needs them.

Apex SOQL syntax keywords and what each part does

SOQL partDescription
SELECTLists the fields to retrieve from each record.
fieldsField API names such as Id, Name, Phone, or CreatedDate. SOQL does not use SELECT *.
FROMSpecifies the Salesforce object being queried.
ObjectStandard or custom object API name, for example Account, Contact, or Invoice__c.
WHEREFilters records by one or more conditions.
ORDER BYSorts returned rows in ascending or descending order.
LIMITRestricts the number of rows returned.
OFFSETSkips rows before returning results, usually for simple paging.
FOR VIEWUpdates the LastViewedDate value for returned records.
FOR REFERENCEUpdates the LastReferencedDate value for returned records.
UPDATE VIEWSTATUsed only for supported Salesforce Knowledge article view-stat use cases.

The API names of the fields are used in the SELECT statement. Use the field API name, not the field label shown to users. Custom fields end with __c, and custom relationship names often end with __r.

Basic SELECT and FROM syntax for Salesforce records

The simplest SOQL query names the fields after SELECT and the object after FROM. This query returns account names and phone numbers.

</>
Copy
SELECT Name, Phone
FROM Account

In the Developer Console Query Editor, run only the SOQL statement. In Apex, wrap the SOQL statement in square brackets and assign the result to a list of sObjects.

</>
Copy
List<Account> accounts = [
    SELECT Name, Phone
    FROM Account
];

If Apex code needs to read a field, include that field in the SELECT clause. Otherwise, the record returned by SOQL may not contain the field value you try to access.

Filtering Apex SOQL records with WHERE conditions

The WHERE clause filters records before they are returned. You can compare values, check for nulls, match text patterns, and combine conditions with AND, OR, and parentheses.

</>
Copy
SELECT Id, Name, BillingCity
FROM Account
WHERE BillingCity = 'Hyderabad'
</>
Copy
SELECT Id, Name, NumberOfEmployees, BillingCity
FROM Account
WHERE NumberOfEmployees > 50
AND (BillingCity = 'Hyderabad' OR BillingCity = 'Bengaluru')
Filter needSOQL condition example
Exact matchIndustry = 'Education'
Not equalStatus__c != 'Closed'
Greater thanAmount > 10000
Text patternName LIKE 'Acme%'
Value from a listId IN :accountIds
Not blankEmail != null

SOQL bind variable syntax in Apex

A bind variable allows a SOQL query to use an Apex variable. Add a colon before the Apex variable name inside the query.

</>
Copy
String cityName = 'Hyderabad';

List<Account> accounts = [
    SELECT Id, Name, BillingCity
    FROM Account
    WHERE BillingCity = :cityName
];

The IN operator is commonly used with a Set or List. This is a standard bulk Apex pattern because one query can retrieve records for many IDs.

</>
Copy
Set<Id> accountIds = new Set<Id>();

for (Account acct : Trigger.new) {
    accountIds.add(acct.Id);
}

List<Contact> contacts = [
    SELECT Id, FirstName, LastName, AccountId
    FROM Contact
    WHERE AccountId IN :accountIds
];

ORDER BY, LIMIT, and OFFSET in SOQL queries

Use ORDER BY when row order matters. This is especially important when using LIMIT or OFFSET, because unordered results should not be treated as predictable.

</>
Copy
SELECT Id, Name, CreatedDate
FROM Account
WHERE BillingCity != null
ORDER BY CreatedDate DESC
LIMIT 10
</>
Copy
SELECT Id, Name
FROM Account
ORDER BY Name ASC
LIMIT 20
OFFSET 20

When a query might return no rows, assign the result to a list first instead of a single sObject variable. A single-record assignment can throw an exception when no record is returned.

</>
Copy
List<Account> latestAccounts = [
    SELECT Id, Name
    FROM Account
    ORDER BY CreatedDate DESC
    LIMIT 1
];

if (!latestAccounts.isEmpty()) {
    Account latestAccount = latestAccounts[0];
}

SOQL relationship query syntax for parent and child records

SOQL does not use SQL-style joins. To read related Salesforce records, use relationship query syntax. A child-to-parent query uses dot notation. A parent-to-child query uses a nested SELECT with the child relationship name.

Child-to-parent SOQL syntax with Account.Name

</>
Copy
SELECT Id, FirstName, LastName, Account.Name
FROM Contact
WHERE Account.Name != null

Parent-to-child SOQL syntax with Contacts

</>
Copy
SELECT Id, Name,
    (SELECT Id, FirstName, LastName FROM Contacts)
FROM Account

For custom relationships, check the child relationship name in Object Manager before writing the nested query.

COUNT and aggregate SOQL syntax in Apex

Use COUNT() when you need a number instead of full records.

</>
Copy
Integer contactsWithEmail = [
    SELECT COUNT()
    FROM Contact
    WHERE Email != null
];

For grouped results, use aggregate functions with GROUP BY. Apex receives grouped rows as AggregateResult records.

</>
Copy
List<AggregateResult> results = [
    SELECT Industry, COUNT(Id) totalAccounts
    FROM Account
    WHERE Industry != null
    GROUP BY Industry
];

Common Apex SOQL syntax mistakes to avoid

  • Using SQL-only syntax: SOQL does not support SELECT * or SQL join syntax.
  • Using field labels: Query field API names such as BillingCity, not user-facing labels.
  • Accessing fields not selected: Add every field your Apex logic reads.
  • Writing SOQL in a loop: Collect IDs first and query once outside the loop.
  • Relying on random row order: Add ORDER BY when order matters.
  • Ignoring access requirements: Production Apex should handle sharing, object permissions, and field-level access intentionally.

QA checklist for Apex SOQL syntax examples

  • Check that every object and field uses the correct API name.
  • Verify that the query has a valid SELECT and FROM.
  • Confirm that Apex inline SOQL examples use square brackets.
  • Use bind variables instead of manual string concatenation where possible.
  • Keep SOQL outside loops in trigger and batch examples.
  • Add ORDER BY before LIMIT when row order matters.
  • Test relationship queries with the correct parent or child relationship name.

Official references for Apex SOQL syntax

For deeper reference, compare your queries with Salesforce’s official material: Trailhead: Write SOQL Queries and the Salesforce Apex Developer Guide for SOQL.

In our upcoming Salesforce developer tutorials we will learn about various SOQL syntax topics, including condition expression syntax using the WHERE clause and field expression syntax. You can also continue with the Salesforce Developer Tutorial series.

Apex SOQL syntax FAQs

What is the basic SOQL syntax in Apex?

The basic syntax is SELECT fields FROM ObjectName WHERE conditions. In Apex, place the query inside square brackets, for example List<Account> accounts = [SELECT Id, Name FROM Account];.

Can I use SELECT * in SOQL?

No. SOQL does not use SELECT *. List the fields you need, such as SELECT Id, Name, Phone FROM Account. Explicit field names also make Apex code easier to review.

How does the IN operator work in Apex SOQL?

Use IN with a collection and a bind variable, such as WHERE AccountId IN :accountIds. This is useful when querying records related to many IDs.

How is SOQL different from SQL?

SOQL is Salesforce-specific. It uses object and field API names, does not support SQL-style joins, and reads related records through relationship query syntax.

Should SOQL be written inside an Apex loop?

No. Avoid SOQL inside loops because Apex has governor limits. Collect values in a set or list, run one query outside the loop, and process the returned records.

Apex SOQL syntax summary for beginners

In this Salesforce Developer Tutorial, we learned that Apex SOQL syntax starts with SELECT fields and FROM an object. Optional clauses such as WHERE, ORDER BY, LIMIT, and OFFSET make the query more precise. In Apex code, prefer bind variables, query outside loops, use correct API names, and retrieve only the fields your logic needs.