How do you make LIKE match a literal % or _ character in SQL?
answer
- the wildcard has to lose its power
- an optional clause on the predicate itself
- you nominate a character, then prefix it
- standard SQL supplies no default for you
basics
~20 sNominate an escape character with the ESCAPE clause and put it in front of the wildcard you want taken literally, as in code LIKE '%!_%' ESCAPE '!'. Standard SQL defines no default escape character, so always declare one.
solid answer
~50 sUse the predicate's `ESCAPE` clause. You nominate a single character, and any `%`, `_` or copy of that character preceded by it is treated as literal text: `WHERE code LIKE '100!% off' ESCAPE '!'` finds the exact string `100% off`. To match the escape character itself, double it (`'!!'` with `ESCAPE '!'`). Standard SQL has **no** default escape character — without the clause, `%` and `_` are always wildcards. Engines differ on defaults: PostgreSQL and MySQL treat a backslash as the escape character even without the clause, while SQL Server and SQLite have no default at all. Backslash is also a poor choice because some engines process it inside string literals too, so pick a character that cannot appear in your data — `!` or `#` — and declare it explicitly. That is the portable answer.
code
sql · 7 lines-- Over-matching: the underscore is a wildcard
SELECT code FROM products
WHERE code LIKE 'AB_%'; -- matches 'ABC1', 'ABX9', 'AB_1'
-- Fixed: the underscore is literal, the trailing % still a wildcard
SELECT code FROM products
WHERE code LIKE 'AB!_%' ESCAPE '!'; -- matches 'AB_1' onlygo deeper
Know that % and _ can be searched for literally, and that the ESCAPE clause is what makes it happen. Be able to write one pattern that finds a literal underscore.
Explain the mechanics: which characters the escape character may precede, how to match the escape character itself by doubling it, and that standard SQL defines no default escape character.
Show that you handle patterns built from data you did not write: escape the escape character first, then the wildcards, and choose an escape character that cannot appear in the searched values.
Own the convention. Pattern-building duplicated across services drifts, especially between engines with different escape defaults; decide on one shared helper and one declared escape character, and make over-matching visible in tests.
## The problem Inside a `LIKE` pattern, `%` and `_` are metacharacters. If the text you are actually looking for contains one of them, a naive pattern silently over-matches. `WHERE discount_label LIKE '%50%%'` does not mean "contains 50%" — the trailing `%` is just another wildcard, so it means "contains 50", and `'50 units'` comes back too. The worst case is `_`: `WHERE code LIKE '%_%'` matches every value with at least one character, which is usually the entire table. ## The ESCAPE clause The standard predicate is: ```sql <value> [NOT] LIKE <pattern> [ESCAPE <single character>] ``` The `ESCAPE` clause nominates one character. Inside the pattern, that character strips the special meaning from the character that follows it: ```sql SELECT * FROM products WHERE code LIKE 'AB!_%' ESCAPE '!'; -- matches 'AB_1', 'AB_XYZ'; does NOT match 'ABC1' ``` The escape character is followed by `%`, `_`, or itself. To search for the escape character literally, write it twice: with `ESCAPE '!'`, the pattern `'!!'` means a single literal `!`. The standard treats an escape character followed by anything else as an error; engines vary in how strictly they enforce that, so do not rely on other combinations. ## There is no default in standard SQL This is the fact interviewers probe. In standard SQL, if you omit `ESCAPE`, **no** character is an escape character — `%` and `_` are unconditionally wildcards. Engines diverge here: - **PostgreSQL** and **MySQL** treat a backslash as the escape character for `LIKE` even when the clause is absent. - **SQL Server** and **SQLite** have no default; you must write `ESCAPE` (T-SQL additionally offers bracket character classes such as `[%]`, but that is a dialect extension, not the portable answer). So the same pattern can behave differently on two engines. Writing `ESCAPE` explicitly removes the ambiguity, and it costs you one clause. ## Why backslash is a bad choice Backslash is the intuitive pick and the wrong one. In MySQL, backslash is *also* an escape character inside string literals by default, so the literal you type is processed twice and you end up doubling backslashes to get one through. Choosing a character that has no other meaning — `!`, `#`, `|` — and declaring it with `ESCAPE` sidesteps the whole layering problem. Pick one that cannot occur in the searched data, or escape it too. ## Escaping values that come from elsewhere When the pattern is assembled from a value you did not write — a search box, an imported list, a stored prefix — you must escape that value's own `%`, `_` and escape characters before concatenating it into the pattern. Order matters: escape the escape character **first**, then the wildcards, otherwise you re-escape the escape characters you just inserted and corrupt the pattern. Note this is a *correctness* concern, entirely separate from how you bind values into the statement. ## Worked comparison ```sql -- Wrong: the user's underscore is a wildcard WHERE code LIKE '%A_1%'; -- matches 'AB1', 'AX1', ... -- Right: the underscore is literal WHERE code LIKE '%A!_1%' ESCAPE '!'; -- matches 'A_1' only ``` A useful sanity check when debugging an over-matching filter: count the rows returned by the pattern with all wildcards removed. If the filtered count is suspiciously close to the table count, an unescaped `_` or `%` from the search text is usually the reason. ## Interaction with NOT LIKE `ESCAPE` attaches to the predicate, not to the pattern literal, and it works identically under negation: `WHERE code NOT LIKE '%!_%' ESCAPE '!'` returns the rows whose code contains no literal underscore. ## What an interviewer is listening for Three things: that you reach for `ESCAPE` rather than trying to "quote" the wildcard some other way; that you know standard SQL has no default escape character and engine defaults differ; and that you double the escape character to match it literally. A candidate who says "just use a backslash, it always works" has not been bitten by an engine where it does not.
- With ESCAPE '!', how do you match a value containing a literal exclamation mark?Double it: the pattern `'%!!%' ESCAPE '!'` matches any value containing a single literal `!`. The escape character is allowed to escape `%`, `_` or itself, and doubling is how you get it through as data. This is also why you should pick an escape character that does not otherwise occur in the searched text — otherwise every occurrence needs doubling.
- Why is WHERE note LIKE '%100%%' a bug when you meant to find the text 100%?The trailing `%` is read as a wildcard, so the pattern reduces to "contains 100" and returns `'100 units'` as well. You need `LIKE '%100!%%' ESCAPE '!'`, where `!%` is a literal percent sign and the final `%` is still a wildcard. It is a silent bug: the query runs and returns a superset, so nobody notices until a report is wrong.
saying these in an interview costs you the question
- Assuming a backslash always escapes wildcards without an ESCAPE clause
- Trying to escape a wildcard by doubling it, as in '%%'
- Thinking ESCAPE changes the quoting of the string literal
- Escaping the wildcards before the escape character when building a pattern
- Believing a bound parameter stops % and _ acting as wildcards