SOQL vs SQL: the differences that trip everyone up
SOQL looks enough like SQL that experienced database people assume they already know it — right up until their first query throws an error. SOQL (Salesforce Object Query Language) is a query language over the Salesforce object model and its API, not over tables, and that changes more than the name. Here are the differences that actually trip people up, with side-by-side examples.
1. There is no SELECT *
Every field must be listed explicitly. For quick exploration, newer API versions accept
FIELDS(ALL), FIELDS(STANDARD), or FIELDS(CUSTOM), but
FIELDS(ALL) requires a LIMIT of 200 or fewer — it's a browsing tool, not a
production pattern.
-- SQL: SELECT * FROM accounts SELECT Id, Name, Industry, AnnualRevenue FROM Account
2. You query exactly one object
The FROM clause names a single object — there's no listing two tables and joining them in
the WHERE clause. Related data is reached through relationship paths defined by lookup and
master-detail fields.
3. There is no JOIN keyword
Instead of joins, SOQL traverses relationships: dot notation walks up to a parent, and a nested subquery walks down to children.
-- SQL: SELECT c.last_name, a.name FROM contacts c JOIN accounts a ON ... SELECT LastName, Account.Name, Account.Owner.Name FROM Contact
This is a big enough topic that it has its own guide: JOINs in SOQL: how relationship queries work.
4. = null instead of IS NULL
SQL's IS NULL / IS NOT NULL don't exist. SOQL compares against
null directly:
SELECT Id, Name FROM Contact WHERE Email = null SELECT Id, Name FROM Contact WHERE Email != null
5. No expressions in the SELECT list
No CASE, no string concatenation, no arithmetic between columns. The select list is
fields, relationship paths, and aggregate functions — formatting and derived values happen in your
code (or in formula fields on the object). A handful of server-side functions exist, such as
toLabel() for picklist labels, FORMAT() for localized output, and
convertCurrency() for multi-currency orgs.
6. Date filtering uses literals, not functions
There's no GETDATE() or DATEADD(). SOQL has named date literals like
TODAY, THIS_FISCAL_QUARTER, and LAST_N_DAYS:30 — unquoted
keywords evaluated at query time. See the full
SOQL date literals cheat sheet.
-- SQL: WHERE created_at >= DATEADD(day, -30, GETDATE()) WHERE CreatedDate = LAST_N_DAYS:30
7. Aggregates exist, but with house rules
COUNT, SUM, AVG, MIN, MAX,
GROUP BY, and HAVING all work — but aliases are written without
AS, unaliased aggregates come back named expr0, expr1, and so
on, and in Apex an aggregate query is limited to 2,000 result rows. Details and examples are in
SOQL aggregate queries.
8. SOQL only reads
There is no INSERT, UPDATE, or DELETE statement. Writes go
through a separate path entirely (DML in Apex, or create/update/delete calls in the APIs). A SOQL
query can never modify data — which is also why a read-only tool can safely expose it.
9. Results are governed and capped
Salesforce is multi-tenant, so queries run under governor limits: an Apex transaction can retrieve at
most 50,000 rows, OFFSET tops out at 2,000, and large extracts belong in the Bulk API
rather than paginated SOQL. If a query "works in dev but dies in production", a limit is usually why.
10. Text matching is case-insensitive
Comparisons and LIKE on standard text fields ignore case — WHERE Name LIKE
'%acme%' matches "ACME Corp". (Fields explicitly configured as case-sensitive unique are the
exception.) Wildcards and the rest of the filter toolbox are covered in
the SOQL WHERE clause guide.
Quick translation table
| You'd write in SQL | You write in SOQL |
|---|---|
SELECT * FROM accounts | SELECT Id, Name, Industry FROM Account |
JOIN accounts a ON c.account_id = a.id | SELECT LastName, Account.Name FROM Contact |
WHERE email IS NULL | WHERE Email = null |
WHERE created_at >= DATEADD(day,-30,GETDATE()) | WHERE CreatedDate = LAST_N_DAYS:30 |
SELECT COUNT(*) FROM cases | SELECT COUNT() FROM Case |
GROUP BY stage HAVING SUM(amount) > 100000 | GROUP BY StageName HAVING SUM(Amount) > 100000 |