How to show tables in SQLite
List every table in a SQLite database with .tables, sqlite_schema or PRAGMA table_list, and filter out views, FTS shadow tables and internal tables.
Quick Answer
SQLite has no SHOW TABLES. In the sqlite3 shell, use .tables:
sqlite3 shop.db
sqlite> .tables
From SQL (Python, Node, any app), query the schema table:
SELECT name FROM sqlite_schema
WHERE type = 'table' AND name NOT LIKE 'sqlite\_%' ESCAPE '\'
ORDER BY name;
sqlite_schema is the newer name for sqlite_master. Both work.
Show tables in the sqlite3 shell
.tables prints table and view names in columns. Give it a pattern to filter. It uses LIKE rules, so % is the wildcard and matching is case-insensitive:
sqlite> .tables
Order Items customers orders
big_orders notes notes_config ...
sqlite> .tables cust%
customers
sqlite> .tables 'Order%'
Order Items orders
The last example shows the case-insensitivity: 'Order%' matched both Order Items and orders. Quote patterns that contain spaces.
| Shell command | Shows |
|---|---|
.tables | Tables and views in every attached database |
.tables pattern | Only names matching a LIKE pattern |
.schema tablename | The CREATE statements for a table and its indexes |
.databases | The main, temp and attached database files |
In VisuaLeaf
See every table in a SQLite file with VisuaLeaf
VisuaLeaf opens a SQLite file the way a viewer should: pick the .db or .sqlite file, with no server and no connection string, and its tables appear in the connection tree. You don't need .tables or a query against sqlite_schema to find out what's inside.
From the tree, right-click a table and choose Open Table Query to browse its rows in a grid, with primary and foreign key badges on the column headers, or Tables Info to see its columns and indexes. To see how the tables relate, open Visual Schema. It draws an ER diagram from the foreign keys inside the file, which is often the quickest way to make sense of a database an app created for you.
See the SQL Table docs.
List tables with SQL
Every SQLite database has a built-in table that holds one row per table, index, view and trigger:
SELECT type, name FROM sqlite_schema ORDER BY type, name;
On SQLite 3.37 or newer, PRAGMA table_list is more useful, because it labels each entry and covers every attached database:
SELECT schema, name, type
FROM pragma_table_list
WHERE type IN ('table', 'virtual')
AND name NOT LIKE 'sqlite\_%' ESCAPE '\'
ORDER BY schema, name;
| Method | Includes views? | Temp and attached DBs? | Internal sqlite_ tables? |
|---|---|---|---|
.tables | Yes | Yes, prefixed (temp.scratch, other.archive) | No |
sqlite_schema | Only if you don't filter on type | No. Use temp.sqlite_schema or other.sqlite_schema | Yes |
pragma_table_list | Yes, labelled view | Yes, with a schema column | Yes, labelled |
What we found testing this
We built a database with tables, a view, an index, an FTS5 full-text table, AUTOINCREMENT and ANALYZE statistics, then listed it every way we could:
- The common
NOT LIKE 'sqlite_%'filter drops real tables. InLIKE,_is a wildcard too, so a table namedsqliteusersvanished from the list. Escape it:NOT LIKE 'sqlite\_%' ESCAPE '\'. - One full-text table shows up as six.
CREATE VIRTUAL TABLE notes USING fts5(body)made.tablesalso listnotes_config,notes_content,notes_data,notes_docsizeandnotes_idx.pragma_table_listmarks those asshadow, so filtering ontype IN ('table','virtual')hides them. .tableshides SQLite's own tables butsqlite_schemadoesn't.sqlite_sequence(from AUTOINCREMENT) andsqlite_stat1(from ANALYZE) appeared in the SQL query, not in.tables.sqlite_schemaonly covers the main database. With a temp table and an attached file,.tablesshowedtemp.scratchandother.archive, the plain query didn't, andpragma_table_listreturned both with their schema names.
sqlite> SELECT schema, name, type FROM pragma_table_list ORDER BY 1, 2;
main|Order Items|table
main|big_orders|view
main|customers|table
main|notes|virtual
main|notes_config|shadow
...
other|archive|table
temp|scratch|tableFrom Python and Node.js
Python's built-in sqlite3 module. Use a raw string so the backslash reaches SQLite:
import sqlite3
con = sqlite3.connect("shop.db")
rows = con.execute(r"""
SELECT name FROM sqlite_schema
WHERE type = 'table' AND name NOT LIKE 'sqlite\_%' ESCAPE '\'
ORDER BY name
""").fetchall()
print([r[0] for r in rows])
This still lists FTS shadow tables such as notes_data. Query pragma_table_list instead, as in the Node example, to skip them.
Node.js with better-sqlite3. .pluck() returns plain names instead of row objects:
import Database from 'better-sqlite3'
const db = new Database('shop.db', { readonly: true, fileMustExist: true })
const tables = db.prepare(`
SELECT name FROM pragma_table_list
WHERE schema = 'main' AND type = 'table'
AND name NOT LIKE 'sqlite\\_%' ESCAPE '\\'
ORDER BY name`).pluck().all()
console.log(tables) // [ 'Order Items', 'customers', 'orders', 'sqliteusers' ]
Why no tables show up
- You opened the wrong file, and SQLite created it.
sqlite3 typo.dbsilently creates an empty 0-byte file, so.tablesprints nothing. Check the path with.databases. - The data is still in the WAL file. If the database uses WAL mode and you copied only the
.dbfile, recent tables can be missing. Copy the-walfile too. See how to open a SQLite file. - The table is in an attached database. Use
pragma_table_listor.tables, not a plainsqlite_schemaquery.
Frequently Asked Questions
Is there a SHOW TABLES command in SQLite?
No. SHOW TABLES is MySQL syntax. Use .tables in the sqlite3 shell, or query sqlite_schema (also called sqlite_master) from SQL.
What is the difference between sqlite_master and sqlite_schema?
None. sqlite_schema is the name used since SQLite 3.33; sqlite_master still works as an alias.
How do I list only tables, not views?
Filter on type: WHERE type = 'table' in sqlite_schema, or type IN ('table', 'virtual') in pragma_table_list. The .tables command always includes views.
How do I count rows in every table?
SQLite keeps no row counts, so you have to run SELECT COUNT(*) on each table. In a script, loop over the table names and run a count for each.