FluentDBFluentDB
SQLite guides

SHOW TABLES in SQLite: listing tables and describing a schema

By Kevin Piacentini, Software Engineer & Founder of FluentDB·

If you have arrived here after typing SHOW TABLES; into SQLite and getting a syntax error, the explanation is short: SHOW TABLES and DESCRIBE are MySQL commands, and SQLite does not have them. Neither is standard SQL.

SQLite has two different answers instead, and knowing which one you need is the part that trips people up. There are dot-commands for the sqlite3 shell, and there is real SQL that works everywhere, including from Python, Node, or any other client.

The short answer

If you are sitting in the sqlite3 command-line shell:

bash
.tables                  -- list every table
.schema                  -- show the CREATE statements for everything
.schema users            -- show the CREATE statement for one table
.databases               -- list attached databases

If you are writing SQL, from an application or a GUI, use these instead. They work anywhere:

sql
-- list every table
SELECT name FROM sqlite_master WHERE type = 'table' ORDER BY name;

-- describe one table
PRAGMA table_info('users');

Why .tables is not the answer you want

This is the single most common source of confusion, so it is worth being precise. Commands beginning with a dot are not SQL. They are features of the sqlite3 command-line program, which interprets them itself and never sends them to the database engine.

That is why this works in a terminal but fails the moment you put it in your code:

text
# In the sqlite3 shell: works
sqlite> .tables
orders  users

# In Python: fails
>>> cur.execute(".tables")
sqlite3.OperationalError: near ".": syntax error
Rule of thumb: if a command starts with a dot, it only exists in the shell. If you need it from code, there is always a SQL or PRAGMA equivalent, and the rest of this page is those equivalents.

Listing tables from SQL

Every SQLite database carries its own catalogue in a table called sqlite_master. Tables, views, indexes and triggers are all rows in it, so listing tables is an ordinary query:

sql
SELECT name
FROM sqlite_master
WHERE type = 'table'
  AND name NOT LIKE 'sqlite_%'
ORDER BY name;

The NOT LIKE 'sqlite_%' filter matters. SQLite keeps internal objects such as sqlite_sequence, created by AUTOINCREMENT, in the same catalogue, and you almost never want those in a list you show to a person.

To include views as well, widen the filter to type IN ('table', 'view'). To get the original DDL for each object, select the sql column, which holds the exact CREATE statement as it was written.

Since SQLite 3.37.0 (2021-11-27) there is also PRAGMA table_list, which returns the schema, name, type, column count and whether the table is WITHOUT ROWID or STRICT. It is tidier than sqlite_master when it is available to you.

Describing a table: PRAGMA table_info

The closest thing to MySQL's DESCRIBE is PRAGMA table_info:

sql
PRAGMA table_info('users');

It returns one row per column:

text
cid  name       type     notnull  dflt_value  pk
---  ---------  -------  -------  ----------  --
0    id         INTEGER  0                    1
1    name       TEXT     1                    0
2    email      TEXT     0                    0
3    created_at TEXT     0        CURRENT_TIMESTAMP  0

notnull is 1 when the column is NOT NULL. pk is 0 for ordinary columns, and for primary key columns it is the 1-based position within the key, which is how you read a composite primary key. dflt_value is the default expression as written.

One caveat worth knowing: PRAGMA table_info does not include generated or hidden columns. If a table uses them, use PRAGMA table_xinfo instead, which does.

If you would rather have this as a normal result set you can join against, SQLite exposes pragmas as table-valued functions too:

sql
SELECT name, type, "notnull", pk
FROM pragma_table_info('users');

Seeing the original CREATE statement

PRAGMA table_info tells you the shape of a table, but not how it was declared. For constraints, CHECK clauses and exact formatting, read the DDL SQLite stored when the table was created:

sql
SELECT sql FROM sqlite_master WHERE name = 'users';

In the shell, .schema users prints the same thing. This is usually the fastest way to understand a table you did not write, because it shows intent, not just structure.

Indexes, foreign keys, and attached databases

The rest of the catalogue is a pragma away:

sql
PRAGMA index_list('users');          -- indexes on the table
PRAGMA index_info('idx_users_email'); -- columns in one index
PRAGMA foreign_key_list('orders');    -- foreign key constraints
PRAGMA database_list;                 -- attached databases

PRAGMA database_listis the honest answer to "how do I show all databases". SQLite has no server and therefore no global registry of databases: a database is just a file. What the pragma lists is what your current connection has open, which is main, temp, and anything you have ATTACHed.

Doing this from application code

The same queries work from any language, because they are ordinary SQL. In Python, where .tables fails, this is the equivalent:

text
import sqlite3

con = sqlite3.connect("app.db")
tables = [r[0] for r in con.execute(
    "SELECT name FROM sqlite_master "
    "WHERE type = 'table' AND name NOT LIKE 'sqlite_%' ORDER BY name"
)]

for t in tables:
    cols = con.execute(f"PRAGMA table_info('{t}')").fetchall()
    print(t, [c[1] for c in cols])

The same two statements are what any GUI runs behind the scenes when it draws you a table list, including our free browser-based SQLite viewer, which lists tables straight out of sqlite_master.

A quick translation table

If you are arriving from MySQL or PostgreSQL:

MySQL and PostgreSQL commands and their SQLite equivalents
MySQL / PostgresSQLite shellSQLite SQL
SHOW TABLES;.tablesSELECT name FROM sqlite_master WHERE type = 'table';
DESCRIBE users;.schema usersPRAGMA table_info('users');
SHOW CREATE TABLE users;.schema usersSELECT sql FROM sqlite_master WHERE name = 'users';
SHOW DATABASES;.databasesPRAGMA database_list;
SHOW INDEX FROM users;.indexes usersPRAGMA index_list('users');

Run these against a real database

Our free SQLite viewer opens a .sqlite, .db or .sqlite3 file in your browser, with nothing to install and no upload, so you can try the queries on this page against your own data.

Open the free SQLite viewer

Or stop memorising pragmas

FluentDB shows your SQLite schema without a single command, edits rows in place, and has an AI co-pilot that writes the SQL when you ask in plain English.

Download FluentDB for Mac

SQLite schema inspection FAQ

Does SQLite have SHOW TABLES?

No. SHOW TABLES is MySQL syntax and SQLite will reject it with a syntax error. In the sqlite3 command-line shell use .tables, and from SQL use SELECT name FROM sqlite_master WHERE type = 'table'.

What is the SQLite equivalent of DESCRIBE table?

PRAGMA table_info('your_table'), which returns one row per column with its name, declared type, whether it is NOT NULL, its default value, and its position in the primary key. In the sqlite3 shell, .schema your_table shows the original CREATE TABLE statement instead.

Why does .tables fail in my Python or Node code?

Because dot-commands are features of the sqlite3 command-line shell, not of SQLite itself. The database engine never sees them. From application code, query sqlite_master or use PRAGMA table_info instead, both of which are real SQL.

How do I list the columns of a table in SQLite?

PRAGMA table_info('your_table') returns one row per column. If you need it as a normal result set you can also use SELECT name FROM pragma_table_info('your_table'), which works as a table-valued function inside a regular query.

How do I show all databases in SQLite?

SQLite has no server, so there is no global list of databases. What exists is the set attached to your current connection: .databases in the shell, or PRAGMA database_list from SQL, which shows main, temp, and anything you have ATTACHed.

How do I see the indexes and foreign keys on a table?

PRAGMA index_list('your_table') lists the indexes, and PRAGMA foreign_key_list('your_table') lists the foreign key constraints. Both take the table name and return one row per item.