Menu
Try in Playground

SQLite WHERE Clause: Filter Rows with Conditions, LIKE, IN, BETWEEN

How the WHERE clause filters rows in SQLite — comparison operators, AND/OR, LIKE, IN, BETWEEN, and the NULL pitfall that catches everyone.

This page includes runnable editors — edit, run, and see output instantly.

WHERE Filters Rows One at a Time

SELECT without WHERE returns every row in the table. That's rarely what you want. WHERE lets you keep only the rows that match a condition — SQLite walks the table, evaluates the condition against each row, and keeps the ones where it's true.

Three rows come back: Neuromancer, Hyperion, and The Martian. The condition year > 1980 was tested against each row, and only the matches survived.

The mental model: WHERE is a filter sitting between FROM and the columns you select. Anything that evaluates to true passes through.

Comparison Operators

The basics work the way you'd expect:

= for equality, != or <> for "not equal," and <, <=, >, >= for ordering. String comparisons use the same operators — author = 'Asimov' matches exactly, character for character.

One thing to know: SQL uses single quotes for string literals. Double quotes are for identifiers (column or table names). WHERE author = "Asimov" might work in SQLite for historical reasons, but it's not portable and can silently misbehave when the "string" happens to match a column name. Stick with single quotes.

AND, OR, and Parentheses

Real queries usually combine conditions. AND requires both sides to be true; OR requires at least one:

The first query filters for recent and short books. The second pulls books by either author.

When you mix AND and OR, precedence bites people. AND binds tighter than OR, so:

reads as Herbert OR (Gibson AND year > 1980) — every Herbert book regardless of year, plus Gibson books after 1980. Probably not what you meant. Wrap your intent in parentheses:

When in doubt, parenthesize. The query optimizer doesn't care, and the next person reading it will thank you.

NULL Doesn't Behave Like a Value

This is the WHERE-clause trap that catches everyone once. NULL in SQL means "unknown," and unknowns can't be compared. column = NULL is not false — it's NULL, which WHERE treats as "skip this row."

IS NULL and IS NOT NULL are the only operators that test NULL directly. Burn those into your fingers — every other comparison with NULL returns NULL and silently drops rows.

The same rule applies to negation. WHERE author != 'Asimov' does not return rows where author IS NULL, because NULL != 'Asimov' is also NULL. If you want NULLs included, ask for them explicitly: WHERE author != 'Asimov' OR author IS NULL.

IN and BETWEEN: Shortcuts You'll Use Daily

IN checks membership in a list. It's a cleaner way to write a chain of ORs:

BETWEEN checks a range, inclusive on both ends:

year BETWEEN 1980 AND 2000 is identical to year >= 1980 AND year <= 2000 — just shorter. One thing to remember: both bounds are included. If you want exclusive bounds, write the comparisons out.

A quick note about IN and NULL: WHERE column NOT IN (1, 2, NULL) will return no rows ever, because comparing anything to NULL yields NULL. Filter out NULLs from your list, or handle them with IS NULL separately.

LIKE for Pattern Matching

LIKE does string pattern matching with two wildcards:

  • % matches any sequence of characters (including none).
  • _ matches exactly one character.

By default, SQLite's LIKE is case-insensitive for ASCII letters — 'Dune' LIKE 'dune' is true. That's surprising if you're coming from Postgres, where LIKE is case-sensitive and ILIKE is the case-insensitive version. (SQLite has no ILIKE.)

If you need case-sensitive matching, you have two options. Toggle the global pragma:

PRAGMA case_sensitive_like = ON;

Or use GLOB, which is always case-sensitive and uses Unix-style wildcards (* for any sequence, ? for one character):

GLOB 'd*' would match nothing here — case matters.

Filtering Dates

SQLite stores dates as text (typically YYYY-MM-DD or full ISO 8601), which means string comparisons happen to also work as date comparisons — as long as you stick to the ISO format:

Because '2024-06-01' < '2024-11-08' is true both as strings and as dates, these queries do what you'd expect. If you store dates in any other format ('15/01/2024', 'Jan 15 2024'), comparisons will silently produce wrong results. Always use ISO 8601 — your future self will be happy.

For trickier date math (extracting the year, comparing to "today"), SQLite has the date(), strftime(), and julianday() functions. We'll cover those in the date-and-time chapter.

Putting It Together

A query that uses several of these at once:

Read it line by line: keep rows with a known year, in range, by one of two authors or long enough, and not a draft. That's the WHERE clause doing what it does best — combining small, readable conditions into precise filters.

Two habits worth keeping:

  • Indent each condition on its own line. Long WHERE clauses get unreadable fast as one giant line.
  • Comment the intent where the condition isn't obvious. -- exclude drafts is cheap insurance.

Next: Operators and NULL in Detail

The WHERE clause is mostly operators applied to columns, and NULL quietly changes how every operator behaves. The next page goes deeper on SQLite's operator set — arithmetic, string concatenation with ||, the IS family, three-valued logic — so the surprises stop being surprises.

Frequently Asked Questions

How does the WHERE clause work in SQLite?

WHERE filters rows from a query by testing a condition against each row. Rows where the condition evaluates to true are kept; rows where it's false or NULL are dropped. It goes right after FROM: SELECT ... FROM table WHERE condition.

How do I combine multiple conditions in a SQLite WHERE clause?

Use AND and OR. AND requires both sides to be true; OR only needs one. AND binds tighter than OR, so wrap mixed conditions in parentheses to be explicit: WHERE (a OR b) AND c.

Why doesn't WHERE column = NULL work in SQLite?

NULL means "unknown," so any comparison with = or != returns NULL instead of true or false — and rows are only kept when the condition is true. Use IS NULL and IS NOT NULL instead. They're the only operators that test for NULL directly.

Is the SQLite WHERE clause case-sensitive for LIKE?

By default, LIKE is case-insensitive for ASCII characters — 'Hello' LIKE 'hello' is true. For full case-sensitivity, set PRAGMA case_sensitive_like = ON; or use GLOB, which is always case-sensitive and uses Unix-style wildcards (* and ?).

Coddy programming languages illustration

Learn to code with Coddy

GET STARTED