Without ORDER BY, Row Order Is Undefined
A SELECT without ORDER BY returns rows in whatever order SQLite finds convenient. It often looks like insertion order on a small table, which lulls people into trusting it. Don't. The moment an index gets used, or the table grows, or a query plan changes, that order can shift without warning.
If you care about the order of your rows, say so explicitly:
ORDER BY name sorts ascending by default. The result comes back Ada, Boris, Chen, Rosa — alphabetically, every time, regardless of how the table is stored on disk.
ASC and DESC
ASC means ascending (smallest to largest, A to Z, oldest to newest). DESC means descending — the reverse. ASC is the default, so you'll almost always see it left out:
That gives you the most recent signups first. Dates stored as ISO 8601 strings (YYYY-MM-DD) sort correctly as text — that's one of the reasons the format is preferred for date columns in SQLite, which has no dedicated date type.
Sorting by Multiple Columns
When the first sort column has ties, SQLite uses the second column to break them. List columns comma-separated, in priority order:
Rows are grouped by country first (FR before US), and within each country, sorted by name. Each column can carry its own direction:
Country ascending, then most-recent-first within each country. The ASC and DESC apply to the column they sit next to — they don't carry over.
Sorting by Expressions and Aliases
ORDER BY accepts any expression, not just column names. Useful for computed values:
The alias revenue from the SELECT list is fair game in ORDER BY. You can also write the expression out again — ORDER BY price * quantity DESC — and it works the same way.
You can also sort by column position, though it's a habit worth avoiding:
SELECT name, price FROM products ORDER BY 2 DESC;
2 means the second column in the select list. It works, but if anyone reorders the columns later, the sort silently changes meaning. Sort by name or alias instead.
Where NULLs Land
NULL is "unknown," and SQLite has to decide where unknown values belong in a sort. The default rule: NULLs come first in ASC, last in DESC.
Ada and Chen show up at the top, before any real date. That's rarely what you want for "most recent first." Override with NULLS LAST:
Now real dates come first, NULLs at the bottom. NULLS FIRST does the opposite. Both are part of standard SQL and work in SQLite 3.30 and later.
Case-Insensitive Sorting with COLLATE NOCASE
SQLite's default text comparison is binary — it sorts by Unicode code points. That means uppercase letters sort before lowercase ones, so 'Zoe' comes before 'apple':
The result is Boris, Zoe, ada, apple — uppercase first, then lowercase. To sort case-insensitively, attach the NOCASE collation:
Now you get ada, apple, Boris, Zoe. NOCASE only treats ASCII A–Z and a–z as equivalent — it doesn't normalize accents or non-ASCII letters. For real internationalized sorting, you'd need an application-level collation, but NOCASE is fine for the common English case.
Random Order
Occasionally you want rows in random order — picking a daily featured item, sampling rows for testing. SQLite's random() function returns a random integer; sort by it:
Each row gets a fresh random value, and the sort shuffles them. Fine for small tables. On big tables, ORDER BY random() is slow — it has to compute a random value for every row and sort the entire result. For sampling a single row from a huge table, fancier approaches (picking a random rowid, for example) are faster.
Common Pitfalls
A few things that bite people:
- Forgetting
ORDER BYand assuming order. Without it, the order is undefined. Even if it looks stable, it isn't. - Sorting numbers stored as text.
'10'sorts before'2'lexicographically. If a column should sort numerically, store it with a numeric affinity (or cast:ORDER BY CAST(value AS INTEGER)). - Mixing ASC and DESC across columns. Each column has its own direction.
ORDER BY a, b DESCsortsaascending andbdescending, not both descending. - Sorting a huge result set just to take the top few rows. Pair
ORDER BYwithLIMITand put an index on the sort column — that's the next page.
Next: LIMIT and OFFSET
Sorting tells SQLite how to arrange rows; LIMIT and OFFSET tell it how many to return and where to start. Together they're the core of pagination and "top N" queries — coming up next.
Frequently Asked Questions
How do I sort results in SQLite?
Add an ORDER BY clause at the end of your SELECT, naming the column to sort by. SELECT * FROM users ORDER BY name; sorts ascending. Add DESC for descending: ORDER BY name DESC. Without ORDER BY, row order is not guaranteed — even if it looks consistent, never rely on it.
How do I sort by multiple columns in SQLite?
List them comma-separated: ORDER BY country, name. SQLite sorts by the first column, then uses the second to break ties. Each column can have its own direction: ORDER BY country ASC, signup_date DESC.
How do I do a case-insensitive sort in SQLite?
Use COLLATE NOCASE in the ORDER BY: ORDER BY name COLLATE NOCASE. By default SQLite sorts text using binary collation, so Zoe comes before apple. NOCASE treats upper and lower case as equal for sorting.
Where do NULLs appear in a sorted SQLite result?
By default, NULLs come first in ascending order and last in descending order. You can override this with NULLS FIRST or NULLS LAST: ORDER BY signup_date DESC NULLS LAST keeps real dates at the top and pushes missing ones to the bottom.