SfSkills Domains Docs GitHub

Home / apex / soql-string-escaping-and-reserved-characters

soql-string-escaping-and-reserved-characters

Use when a SOQL single-quoted string literal contains a character that must be escaped: an apostrophe in a name (O'Brien, Bob's BBQ), a backslash, a tab/newline/other control character, a Unicode character via \uXXXX, or a literal LIKE wildcard (\_ or \%).

Open the skill folder on GitHub


SOQL String Escaping and Reserved Characters

This skill activates when a SOQL single-quoted string literal contains a character the parser treats specially — an apostrophe, a backslash, a control character, a Unicode code point, or a LIKE wildcard you want to match literally. It documents the fixed SOQL escape rule set so the query parses correctly instead of throwing a hard error or matching the wrong records.


Before Starting

Gather this context before working on anything in this domain:


Core Concepts

The escape character and the escape-sequence table

The escape character for SOQL string literals is the backslash. Only the sequences in the table below are valid; the letter sequences are case-insensitive (\n and \N are equivalent):

SequenceMeaning
\n or \NNew line
\r or \RCarriage return
\t or \TTab
\b or \BBell
\f or \FForm feed
\"One double-quote character
\'One single-quote character
\\Backslash
\_Matches a single underscore character — LIKE expression only
\%Matches a single percent sign character — LIKE expression only
\uXXXXUnicode character, where XXXX is the hex code (e.g. é is é)

Any backslash followed by anything else is an error. There is no "unknown escape falls back to literal" behavior — the parser rejects the whole query.

Reserved characters: single quote and backslash

The single quote (') and the backslash (\) are reserved in SOQL. Any reserved character that appears as a literal inside a single-quoted string must be escaped with a preceding backslash, or the query errors. This is why:

The reserved-character rule and the escape-sequence table are two views of the same mechanism: \' and \\ appear in both.

LIKE-only wildcard escapes

In a LIKE expression, % matches any sequence of characters and _ matches any single character. To match a literal % or _, escape it: \% and \_. These two sequences are valid only inside a LIKE expression — using them anywhere else is one of the "any other context" errors. The escape changes match semantics, not just parsing:

Two escaping layers when the query lives in Apex

For inline SOQL ([SELECT ... WHERE Name = 'Bob\'s BBQ']), the bracketed text is SOQL, so you write SOQL escapes directly. For dynamic SOQL, the query is an Apex String first, so Apex string-literal escaping applies to your source, and the runtime string is what the SOQL parser sees. String.escapeSingleQuotes(stringToEscape) adds the escape character (\) before any single quote (') or backslash (\) in a value — exactly the two reserved characters — which is why the Apex Reference Guide recommends it "to help prevent SOQL injection." It does not escape %/_, so it does not neutralize LIKE wildcards.


Common Patterns

Apostrophe-safe literal (the reserved single quote)

When to use: a filter value can contain an apostrophe — person and company names are the usual source (O'Brien, Bob's BBQ).

How it works: in inline SOQL, escape the quote in the literal: WHERE Name = 'Bob\'s BBQ'. When the value is an Apex variable going into dynamic SOQL, prefer a bind variable so you never hand-escape; if you must concatenate, run the value through String.escapeSingleQuotes() first.

Why not the alternative: doubling the quote ('Bob''s BBQ') is SQL, not SOQL, and fails to parse. Leaving the apostrophe raw both errors and is the classic SOQL-injection break-out character.

When to use: the search term itself contains % or _ and the user means those characters literally — e.g. searching product names for "50% off" or a code like A_B.

How it works: escape the wildcard inside the LIKE pattern: WHERE Name LIKE '%50\% off%'. The \% matches a literal percent; the surrounding bare % remain wildcards.

Why not the alternative: an unescaped %/_ from user input is treated as a wildcard, silently widening the result set (a correctness and, for user-driven search, a data-exposure problem). String.escapeSingleQuotes does not fix this — wildcard escaping is separate.

Control characters and Unicode in a literal

When to use: you need a newline, tab, or a specific Unicode character inside a literal (rare in filters, more common when a stored value legitimately contains them).

How it works: use the table sequence — \n, \t, or \uXXXX (e.g. é for é). Never paste a raw backslash-plus-letter that isn't in the table.


Decision Guidance

SituationRecommended approachReason
Value with an apostrophe in dynamic SOQL from user inputBind variable (or queryWithBinds); String.escapeSingleQuotes only if you must concatenateBinding removes the escaping burden and closes injection; see apex/apex-dynamic-soql-binding-safety
Apostrophe in a static, inline literal you controlWrite \' in the query textInline SOQL uses SOQL escapes directly; no Apex layer
User's LIKE term may contain a literal % or _Escape it to \% / \_ in the patternUnescaped wildcards widen matches; escapeSingleQuotes won't help
Literal backslash needed in the valueWrite \\A lone \ outside a valid sequence is a hard error
Newline / tab / Unicode inside a literalUse \n / \t / \uXXXX from the tableThese are the only valid representations
You came from SQL/Oracle and reflexively doubled the quoteReplace '' with \''' is not a SOQL escape

Step-by-step instructions for an AI agent or practitioner working on this task:

  1. Locate every single-quoted literal in the query (inline [SELECT ...] or the dynamic query string) and note which values come from user input.
  2. Escape the reserved characters in each literal: single quote → \', backslash → \\. For user-supplied values in dynamic SOQL, do this by binding (preferred) or String.escapeSingleQuotes(), not by hand.
  3. Handle LIKE wildcards deliberately — decide per %/_ whether it is a wildcard or a literal; escape the literals as \% / \_, and remember escapeSingleQuotes does not touch them.
  4. Represent control/Unicode characters only with valid table sequences (\n, \t, \uXXXX); reject any other backslash use.
  5. Validate by running the escape checker (scripts/check_soql_string_escaping_and_reserved_characters.py) over .soql files or with --query, and by executing the query in a sandbox / Developer Console Query Editor to confirm it parses and returns the intended rows.

Review Checklist

Run through these before marking work in this area complete:


Salesforce-Specific Gotchas

Non-obvious platform behaviors that cause real production problems:

  1. Doubling the quote is a SQL habit that fails in SOQL — 'O''Brien' parses in Oracle/SQL-92 but errors in SOQL; the correct escape is 'O\'Brien'.
  2. A stray backslash is a hard error, not a literal — Windows paths ('C:\temp') and regex fragments ('\d') inside a SOQL literal throw a query error because the backslash isn't part of a defined sequence.
  3. String.escapeSingleQuotes does not escape LIKE wildcards — it handles ' and \ only, so a user-supplied %/_ still behaves as a wildcard and can widen the result set even after "escaping."

Output Artifacts

ArtifactDescription
Correctly escaped SOQL literalA single-quoted literal with \', \\, \%/\_, \uXXXX applied per the escape table so the query parses
scripts/check_soql_string_escaping_and_reserved_characters.pyStdlib checker that flags invalid backslash escapes and LIKE-only escapes used outside LIKE, in .soql files or a --query string
templates/soql-string-escaping-and-reserved-characters-template.mdQuick-reference escape table plus an Apex escaping worksheet to fill in per query

Package files