The essentials

Quick reference

One focused task per row. Jump to the related section for complete, working examples.

UseSyntaxExamples
List visible tablesSELECT table_schema, table_name FROM information_schema.tables WHERE table_type = 'BASE TABLE';View examples
List PostgreSQL relationsSELECT oid::regclass, relkind FROM pg_catalog.pg_class WHERE relnamespace = 'app'::regnamespace;View examples
Resolve the catalog schemaSELECT pg_catalog.current_schema();View examples
Resolve a relation OIDSELECT to_regclass('app.orders');View examples
Find a relation kindSELECT relkind FROM pg_class WHERE oid = 'app.orders'::regclass;View examples
List portable columnsSELECT column_name, data_type, is_nullable FROM information_schema.columns WHERE table_schema = 'app' AND table_name = 'orders';View examples
Render a PostgreSQL typeSELECT format_type(atttypid, atttypmod) FROM pg_attribute WHERE attrelid = 'app.orders'::regclass AND attnum > 0;View examples
Resolve a type safelySELECT to_regtype('pg_catalog.int8');View examples
Show index definitionsSELECT indexrelid::regclass, indisvalid, pg_get_indexdef(indexrelid) FROM pg_index WHERE indrelid = 'app.orders'::regclass;View examples
Show a constraint definitionSELECT pg_get_constraintdef(oid) FROM pg_constraint WHERE conname = 'orders_pkey';View examples
Check table privilegeSELECT has_table_privilege('app_reader', 'app.orders', 'SELECT');View examples
Check schema usageSELECT has_schema_privilege('app_reader', 'app', 'USAGE');View examples
Check function executionSELECT has_function_privilege('app_reader', 'app.total(bigint)', 'EXECUTE');View examples
Describe a catalog objectSELECT pg_describe_object('pg_class'::regclass, 'app.orders'::regclass, 0);View examples
Inspect dependenciesSELECT * FROM pg_depend WHERE refobjid = 'app.orders'::regclass;View examples
Check server version numberSELECT current_setting('server_version_num')::int;View examples
Check recovery stateSELECT pg_is_in_recovery();View examples

information_schema offers SQL-standard, privilege-filtered metadata, while pg_catalog exposes PostgreSQL-specific details needed for operations and tooling. Catalogs are regular relations but direct writes are unsafe; prefer DDL, supported functions, and explicitly selected columns that tolerate version evolution.

Step by step

Detailed examples

01

Choose portability or PostgreSQL detail intentionally

information_schema uses standardized names and exposes only objects the current user can access, making it a good default for portable discovery. pg_catalog includes internal identifiers and PostgreSQL features. Neither is a stable promise for SELECT *, so enumerate columns and test tooling against every supported major release.

List visible base tables portably
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 table_schema, table_name;
Back to quick reference ↑
02

Join pg_class to pg_namespace for relation identity

pg_class describes tables, indexes, sequences, views, materialized views, composite types, and partitioned objects; relkind distinguishes them. Names are unique only within a schema, while OIDs can change after dump/restore. Cast to regclass for readable identity and safe name resolution.

Inventory relation kinds and persistence
SELECT c.oid::regclass AS relation, c.relkind, c.relpersistence,
       c.reltuples, c.relpages
FROM pg_catalog.pg_class c
JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE n.nspname = 'app'
ORDER BY n.nspname, c.relname;
Back to quick reference ↑
03

Use attnum and dropped-column filters correctly

pg_attribute includes system and dropped columns, so filter attnum > 0 and NOT attisdropped. format_type renders type modifiers such as varchar lengths and numeric precision. information_schema.columns separates domains and underlying UDT identity and is preferable for portable clients.

Describe live columns with PostgreSQL detail
SELECT a.attnum, a.attname, pg_catalog.format_type(a.atttypid, a.atttypmod) AS data_type,
       a.attnotnull, a.attidentity, a.attgenerated
FROM pg_catalog.pg_attribute a
WHERE a.attrelid = 'app.orders'::regclass
  AND a.attnum > 0 AND NOT a.attisdropped
ORDER BY a.attnum;
Back to quick reference ↑
04

Inspect constraints and indexes without parsing DDL

pg_constraint connects constraints to relations and pg_index holds index-specific flags and column mappings. pg_get_constraintdef and pg_get_indexdef reconstruct readable definitions, but generated text is for display and migration assistance rather than a cross-version serialization format. Validity flags matter during concurrent builds and staged validation.

List constraints with validated state
SELECT conname, contype, convalidated,
       pg_catalog.pg_get_constraintdef(oid, true) AS definition
FROM pg_catalog.pg_constraint
WHERE conrelid = 'app.orders'::regclass
ORDER BY conname;
Back to quick reference ↑
05

Ask privilege functions instead of inferring ACL text

ACL arrays are compact internal representations and ownership, inheritance, PUBLIC grants, and column grants complicate manual interpretation. has_*_privilege functions answer effective privilege questions for the current role or a named role. Metadata visibility can itself disclose structure, so grant pg_read_all_settings or monitoring roles deliberately.

Audit effective table privileges
SELECT has_table_privilege('app_reader', 'app.orders', 'SELECT') AS can_read,
       has_table_privilege('app_writer', 'app.orders', 'INSERT, UPDATE') AS can_write;
Back to quick reference ↑
06

Use dependency catalogs to explain ownership and drop behavior

pg_depend records database-local dependencies between objects and pg_shdepend covers dependencies on cluster-wide objects such as roles and tablespaces. deptype distinguishes normal, automatic, internal, extension, and other dependency semantics. Catalog joins are version-specific; use pg_describe_object for readable output and never edit dependency rows.

Describe objects that depend on one relation
SELECT d.deptype,
       pg_catalog.pg_describe_object(d.classid, d.objid, d.objsubid) AS dependent
FROM pg_catalog.pg_depend d
WHERE d.refclassid = 'pg_class'::regclass
  AND d.refobjid = 'app.orders'::regclass
ORDER BY dependent;
Back to quick reference ↑
07

Treat catalog access as read-only and version-aware

Direct catalog updates can corrupt metadata and are unsupported even though catalogs are tables. System catalogs are generally database-local, with selected shared catalogs such as pg_database and role catalogs. Standbys expose replayed catalog state read-only; monitoring views can differ from primary state and may be privilege-filtered.

Record server identity before running catalog tooling
SELECT current_setting('server_version_num')::int AS server_version_num,
       current_database(), current_user, pg_is_in_recovery();
Back to quick reference ↑

Sources and further reading

References

Authoritative documentation used to verify and expand this cheat sheet.

  1. PostgreSQL Global Development GroupSystem Catalogspostgresql.org
  2. PostgreSQL Global Development GroupSystem Catalog Overviewpostgresql.org
  3. PostgreSQL Global Development GroupThe Information Schemapostgresql.org
  4. PostgreSQL Global Development Groupinformation_schema.tablespostgresql.org
  5. PostgreSQL Global Development Groupinformation_schema.columnspostgresql.org
  6. PostgreSQL Global Development Grouppg_classpostgresql.org
  7. PostgreSQL Global Development Grouppg_attributepostgresql.org
  8. PostgreSQL Global Development Grouppg_dependpostgresql.org
  9. PostgreSQL Global Development GroupSystem Information Functionspostgresql.org

Help us improve

Found a typo or missing example?

Tell us what would make this cheat sheet clearer, more complete, or more useful.

Share feedback