The essentials
Quick reference
One focused task per row. Jump to the related section for complete, working examples.
| Use | Syntax | Examples |
|---|---|---|
| Connect with a service | psql service=reporting | View examples |
| Override database and role | psql -d appdb -U app_reader | View examples |
| Suppress startup files | psql -X -d appdb | View examples |
| Stop after an error | psql -X -v ON_ERROR_STOP=1 -f migration.sql appdb | View examples |
| Wrap a file atomically | psql -X -1 -v ON_ERROR_STOP=1 -f migration.sql appdb | View examples |
| Execute one SQL command | psql -X -d appdb -c 'SELECT current_timestamp;' | View examples |
| Set a script variable | psql -v tenant=acme -f report.sql appdb | View examples |
| Quote a literal variable | SELECT :'tenant' AS tenant; | View examples |
| Quote an identifier | SELECT count(*) FROM :"table_name"; | View examples |
| List relations | \dt app.* | View examples |
| Describe a relation | \d+ app.orders | View examples |
| Show the current connection | \conninfo | View examples |
| Enable expanded display | \x auto | View examples |
| Select CSV output | \pset format csv | View examples |
| Hide headings and row counts | \t on | View examples |
| Include relative to script | \ir fragments/indexes.sql | View examples |
| Print the query buffer | \p | View examples |
| Capture one result row | SELECT current_user AS actor \gset session_ | View examples |
| Time subsequent commands | \timing on | View examples |
psql is both an interactive SQL terminal and a script runner. Its backslash commands run in the client, while SQL is sent to the server; reliable automation depends on understanding that boundary, quoting variables safely, failing on errors, and avoiding secrets in process arguments or history.
Step by step
Detailed examples
Connect without leaking credentials or trusting an unsafe schema
Use a service definition, password file, or protected environment supplied by a secret manager instead of putting passwords in command arguments. A connection URI can carry TLS policy, but URI-encode special characters. For sessions executing untrusted SQL, use an empty or tightly controlled search_path so attacker-writable schemas cannot shadow objects.
\set ON_ERROR_STOP on
SELECT current_database(), current_user, inet_server_addr(); Note: Invoke with psql service=reporting; store sslmode=verify-full and host identity in pg_service.conf, and protect .pgpass with mode 0600.
Make scripts stop predictably on errors
Without ON_ERROR_STOP, psql continues after script errors and exits successfully in many cases. Set it for automation and wrap related statements in a transaction. --single-transaction makes a file atomic only when its commands are transaction-safe; commands such as CREATE DATABASE and VACUUM cannot run inside its transaction.
\set ON_ERROR_STOP on
ALTER TABLE app.orders ADD COLUMN source text;
UPDATE app.orders SET source = 'legacy' WHERE source IS NULL;
ALTER TABLE app.orders ALTER COLUMN source SET NOT NULL; Note: Invoke with psql -X -1 -f migration.sql appdb; do not include commands that PostgreSQL forbids inside a transaction.
Interpolate values with SQL-aware quoting
psql variables are textual client substitutions. Use :'name' for a SQL literal and :"name" for an identifier; raw :name is safe only for already-controlled SQL fragments. Variables are not server bind parameters, and variable interpolation does not occur inside quoted SQL text.
\set ON_ERROR_STOP on
SELECT order_id, total
FROM app.orders
WHERE tenant_id = :'tenant'
ORDER BY order_id; Note: Invoke with -v tenant=acme; :'tenant' asks psql to quote the value as a SQL literal.
Inspect objects through supported meta-commands
Description commands query catalogs and format the result for humans. Add S for system objects and + for size or detail where supported. Their output is version-specific, so automation should query stable catalog or information-schema columns instead of parsing formatted descriptions.
\d+ app.orders
\di+ app.orders* Note: Run interactively; use catalog queries for machine-readable inventory.
Choose stable output for people or pipelines
Aligned tables are readable interactively; unaligned tuples-only output is easier to consume in simple pipelines. CSV output handles delimiters and quoting better than ad hoc separators. Locale and null rendering can still matter, so prefer a real driver for complex application interchange.
\copy (SELECT id, email FROM app.users ORDER BY id) TO 'users.csv' WITH (FORMAT csv, HEADER true) Note: \copy reads or writes files as the client OS user; server-side COPY uses server filesystem permissions.
Control the query buffer and compose scripts
Meta-commands operate on psql state, not database transactions. i resolves a path from the process working directory, while ir resolves relative to the including script. Use p and to inspect or clear a partially entered statement before accidental execution.
\set ON_ERROR_STOP on
\ir 010_tables.sql
\ir 020_indexes.sql
\ir 030_grants.sql Note: \ir makes nested includes location-independent when the migration directory moves.
Use conditions and captured scalar results deliberately
gset requires exactly one result row and stores each column in a psql variable; NULL unsets the variable. Conditional blocks are evaluated by psql, making them useful for guarded scripts, but authorization must still be enforced by the server. Do not treat client-side conditions as a security boundary.
SELECT current_setting('server_version_num')::int >= 180000 AS supported \gset
\if :supported
\echo 'PostgreSQL 18 feature path'
\else
\warn 'Unsupported server version'
\endif Sources and further reading
References
Authoritative documentation used to verify and expand this cheat sheet.
- PostgreSQL Global Development Grouppsqlpostgresql.org
- PostgreSQL Global Development GroupDatabase Connection Control Functionspostgresql.org
- PostgreSQL Global Development GroupThe Connection Service Filepostgresql.org
- PostgreSQL Global Development GroupThe Password Filepostgresql.org
- PostgreSQL Global Development GroupSchemas and Secure Search Pathspostgresql.org
- PostgreSQL Global Development GroupCOPYpostgresql.org
Help us improve
Found a typo or missing example?
Tell us what would make this cheat sheet clearer, more complete, or more useful.



