Get Started Free

How to list tables in PostgreSQL

List PostgreSQL tables with \dt in psql, or query information_schema or pg_tables from SQL. Covers schemas, views, sizes and why tables go missing.

Updated October 28, 2026 ยท Tested on PostgreSQL 16.14, psql 16

Quick Answer

Connect to the database, then run \dt in psql:

\c myapp
\dt

From SQL, use pg_tables:

SELECT schemaname, tablename
FROM pg_tables
WHERE schemaname NOT IN ('pg_catalog', 'information_schema')
ORDER BY 1, 2;

List tables in psql

\dt lists tables in the schemas on your search_path, which by default means public. Tables only exist inside a database, so connect to the right one first with \c. If you're still in the default postgres database, \dt just says Did not find any relations.

CommandLists
\dtTables in schemas on the search_path (usually just public)
\dt sales.*Every table in the sales schema
\dt *.*Every table in every schema, including pg_catalog
\dt cust*Tables whose names start with cust
\dt+Adds size, persistence, access method and description
\dtvTables and views together
\dvViews only. \dm is materialized views, \ds is sequences
myapp=# \dt
           List of relations
 Schema |   Name    | Type  |  Owner
--------+-----------+-------+----------
 public | Invoices  | table | postgres
 public | customers | table | postgres
(2 rows)

List tables with a SQL query

Meta-commands like \dt only work in psql. In application code, pgAdmin, DBeaver or any other client, query a catalog instead. There are two to choose from, and they don't return the same rows:

-- pg_tables: every table in the database
SELECT schemaname, tablename
FROM pg_tables
WHERE schemaname NOT IN ('pg_catalog', 'information_schema')
ORDER BY 1, 2;

-- information_schema: standard SQL, works on MySQL and SQL Server too
SELECT table_schema, table_name
FROM information_schema.tables
WHERE table_type = 'BASE TABLE'
  AND table_schema NOT IN ('pg_catalog', 'information_schema')
ORDER BY 1, 2;

information_schema.tables only shows tables your role has some privilege on. pg_tables shows all of them. If a table is missing from one query but present in the other, you're looking at a permissions problem, not a missing table.

To include views, drop the table_type filter, or select table_type so you can tell them apart ('BASE TABLE' vs 'VIEW').

What we found testing this

We built one database with an ordinary table, a quoted "Invoices" table, a view, a materialized view, a partitioned table with two partitions, a temp table and a same-named table in a second schema, then compared what each method lists:

Object\dtpg_tablesinformation_schema.tables
Materialized viewNo (use \dm)NoNo
ViewNoNoYes, as VIEW
Partitioned parentYes, as partitioned tableYesYes, as BASE TABLE
Each partitionYes, one row eachYesYes
Temp tableYes, in schema pg_temp_3YesYes, as LOCAL TEMPORARY, so a BASE TABLE filter drops it
public.customers when s2.customers is first on search_pathNo, hiddenYesYes
  • Materialized views are in no table listing. Query pg_matviews or use \dm. If a report "table" is missing everywhere, it's probably one of these.
  • Partitions inflate the count. A table split into 24 monthly partitions shows up 25 times. information_schema can't tell the parent from a partition. In pg_class, filter with NOT relispartition.
  • Row estimates start at -1. After loading 50,000 rows, reltuples was still -1. It only became 50000 after ANALYZE. On PostgreSQL 13 and older, a never-analyzed table shows 0 instead.
  • Capitalised names sort first. "Invoices" came before customers, because catalog names use the name type, which sorts bytewise, not by your database's collation.

List tables in one schema

\dn          -- list schemas first
\dt sales.*  -- then the tables in one of them
SELECT tablename
FROM pg_tables
WHERE schemaname = 'sales'
ORDER BY tablename;

If you work in one schema all the time, put it on your search path, and plain \dt will show its tables:

SET search_path TO sales, public;

List tables with size and row count

\dt+ shows the size of each table on its own. The query below also counts indexes and TOAST data, sorts by size and adds the planner's row estimate, which is instant even on huge tables:

SELECT n.nspname                                  AS schema,
       c.relname                                  AS table,
       pg_size_pretty(pg_total_relation_size(c.oid)) AS total_size,
       c.reltuples::bigint                        AS estimated_rows
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind IN ('r', 'p')   -- ordinary and partitioned tables
  AND NOT c.relispartition       -- count a partitioned table once
  AND n.nspname NOT IN ('pg_catalog', 'information_schema')
ORDER BY pg_total_relation_size(c.oid) DESC;

pg_total_relation_size of a partitioned parent is 0, because the data lives in the partitions. Drop the relispartition line to see each partition's size. For -1 row estimates, see above.

Why a table is missing from the list

  • Wrong database. Check with SELECT current_database(); and switch with \c.
  • It's in another schema. \dt only searches the search_path. Try \dt *.*name*.
  • It's a view, materialized view or foreign table, or it's hidden by a same-named table earlier on the search path. See the comparison table above. \dE lists foreign tables.
  • You don't have privileges on it, and you used information_schema. Query pg_tables instead.

Names with capital letters ("Invoices" above) sort before lowercase ones and must be double-quoted in queries. See relation does not exist.

Frequently Asked Questions

What is the PostgreSQL equivalent of SHOW TABLES?

In psql it is \dt. In SQL, query pg_tables or information_schema.tables. PostgreSQL has no SHOW TABLES statement; SHOW reads configuration settings.

How do I list all tables in all schemas?

Run \dt *.* in psql, or query pg_tables without a schema filter. Exclude pg_catalog and information_schema to hide the system tables.

Why does \dt say "Did not find any relations"?

You are probably connected to a database with no tables in your search_path, often the default postgres database. Connect with \c yourdb, or look in other schemas with \dt *.*.

Does \dt show views?

No. Use \dv for views, or \dtv for tables and views together.

How do I see the columns of a table?

Run \d tablename in psql, or query information_schema.columns for that table from SQL.

VisuaLeaf

See every table and how they connect

VisuaLeaf lists your PostgreSQL schemas and tables in one tree, opens any table in a grid, and draws an ER diagram from your foreign keys, so you can see how tables relate as well as what they are.