SQLite Formatter
Format SQLite queries, schemas and PRAGMA scripts, typeless columns and upserts included.
Your SQLite
Formatted SQLite
SQLite SQL turns up embedded in other things: a string constant in application code, a migration in a mobile app, the output of .schema from the command-line shell. It is usually written compactly because it was never meant to be read on its own, and it is usually the moment you need to read it that something has gone wrong.
With the SQLite dialect selected, the formatter handles the syntax the engine permits and others do not — columns declared with no type at all, PRAGMA statements sitting between ordinary DDL, ON CONFLICT upsert clauses with their excluded. pseudo-table, and AUTOINCREMENT on an integer primary key.
How to use the sqlite formatter
- 1
Paste the query or schema
A query, a
CREATE TABLE, or the whole output of.schemafrom thesqlite3shell. - 2
Choose indentation and keyword case
Two spaces keeps a full schema compact enough to scan; upper-cased keywords separate the SQL from the identifiers.
- 3
Copy back into your migration or source file
The result pastes cleanly into a migration, a Python triple-quoted string or a Swift or Kotlin source file.
SQLite quirks the formatter has to accommodate
- Columns with no type. SQLite uses dynamic typing with type affinity: the declared type is a hint about preferred storage, not a constraint, and it may be omitted entirely. The
tagcolumn in the sample has no type, which is perfectly legal and which a stricter dialect parser would reject. - Type affinity names. There are five affinities — TEXT, NUMERIC, INTEGER, REAL and BLOB — and any declared type maps onto one of them by name matching. A column declared
VARCHAR(255)gets TEXT affinity and happily stores an integer. The formatter prints what you wrote; it does not normalise type names, because the exact spelling is what the affinity rules read. AUTOINCREMENT. Legal only on anINTEGER PRIMARY KEY, which is itself an alias for the internal rowid. It is also usually unnecessary: without it, SQLite already assigns increasing rowids, and adding it costs an extrasqlite_sequencetable plus a guarantee against reuse you may not need.PRAGMA. Configuration statements such asPRAGMA foreign_keys = ONare formatted as standalone statements between DDL, which is exactly how they appear in real migration scripts.ON CONFLICTupserts. The conflict target, theDO UPDATE SETassignments, theexcluded.references to the row that failed to insert, and the optional trailingWHEREare each broken out onto their own lines.STRICTtables. The modern opt-in to real type enforcement is preserved on the tail of aCREATE TABLE. Note that it is incompatible with the typeless column above — aSTRICTtable requires every column to declare one of the five permitted types — which is a rule about SQLite, not about formatting.
ALTER TABLE is narrow, so schemas get rewritten
SQLite supports only a small slice of ALTER TABLE: rename a table, add a column, rename a column, and drop a column. There is no changing a column type, no adding a constraint to an existing table, no reordering.
The standard workaround — create a new table with the shape you want, copy the rows across, drop the original, rename the replacement — is why SQLite migrations tend to contain whole CREATE TABLE statements rather than terse one-line alters. Those long DDL statements are the main thing people bring to this formatter, and a clause-per-column layout makes it much easier to diff the new table against the old.
SQLite Formatter FAQ
Why does a column with no type format without complaint?
Because SQLite allows it. Declared types are affinity hints rather than constraints, and a column may be declared with none at all. The formatter follows the dialect rather than imposing stricter rules.
Does it handle PRAGMA statements?
Yes. They are formatted as ordinary standalone statements, which is what they are — a PRAGMA sits alongside DDL in a migration script rather than inside a statement.
Can it format the output of .schema?
Yes, and it is a common use. Paste the whole dump; each CREATE TABLE, CREATE INDEX and trigger is laid out and separated by a blank line.
Is my database file involved at all?
No. This tool only accepts SQL text. It does not open, read or connect to a .sqlite or .db file, and nothing you paste leaves your browser.
