📦 deps(thirdparty): update snapshots
This commit is contained in:
@@ -0,0 +1,498 @@
|
||||
---
|
||||
name: postgresql-cli
|
||||
description: PostgreSQL interactive terminal (psql) reference and usage guide. Use this skill whenever the user mentions psql, PostgreSQL command-line client, backslash commands, meta-commands, \d commands, database inspection, SQL scripting in PostgreSQL, importing/exporting data with psql, \copy,...
|
||||
risk: unknown
|
||||
source: https://github.com/chaunsin/agent-skills/tree/master/skills/postgresql-cli
|
||||
source_repo: chaunsin/agent-skills
|
||||
source_type: community
|
||||
date_added: 2026-07-01
|
||||
license: Apache-2.0
|
||||
license_source: https://github.com/chaunsin/agent-skills/blob/master/LICENSE
|
||||
---
|
||||
|
||||
# psql — PostgreSQL Interactive Terminal
|
||||
|
||||
psql is PostgreSQL's feature-rich interactive terminal. It lets you write and execute queries, inspect database objects, import/export data, script batch operations, and customize output formatting — all from the command line.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before using psql, verify it is installed and available:
|
||||
|
||||
```bash
|
||||
# Check if psql is installed
|
||||
psql --version
|
||||
|
||||
# If not found, install PostgreSQL client tools:
|
||||
|
||||
# macOS (Homebrew)
|
||||
brew install libpq
|
||||
brew link --force libpq
|
||||
|
||||
# Ubuntu / Debian
|
||||
sudo apt install postgresql-client
|
||||
|
||||
# CentOS / RHEL
|
||||
sudo yum install postgresql
|
||||
|
||||
# Alpine
|
||||
apk add postgresql-client
|
||||
|
||||
# Windows — install PostgreSQL via the official installer or use WSL
|
||||
```
|
||||
|
||||
psql ships as part of the `postgresql-client` package. The server (`postgresql`) is not required — you only need the client to connect to a remote PostgreSQL instance.
|
||||
|
||||
## Quick Reference
|
||||
|
||||
### Connecting
|
||||
|
||||
```
|
||||
# 1. CLI flags
|
||||
psql -h host -p port -U user -d dbname
|
||||
|
||||
# 2. Connection URI
|
||||
# WARNING: Password in URI is visible in shell history and process listings.
|
||||
# Prefer ~/.pgpass for production use (see method 4 below).
|
||||
psql "postgresql://user:YOUR_PASSWORD@host:port/dbname"
|
||||
|
||||
# 3. Environment variables (no flags needed)
|
||||
export PGHOST=localhost
|
||||
export PGPORT=5432
|
||||
export PGDATABASE=mydb
|
||||
export PGUSER=postgres
|
||||
# WARNING: PGPASSWORD is visible in process listings (e.g. `ps aux`).
|
||||
# Use ~/.pgpass in production instead.
|
||||
export PGPASSWORD=YOUR_PASSWORD
|
||||
psql # picks up all params from env
|
||||
|
||||
# 4. ~/.pgpass file (RECOMMENDED for passwords)
|
||||
# Format: hostname:port:database:username:password
|
||||
touch ~/.pgpass && chmod 600 ~/.pgpass
|
||||
# Then manually edit ~/.pgpass and add entries (avoids password in shell history):
|
||||
# hostname:port:database:username:password
|
||||
# Example: localhost:5432:mydb:postgres:YOUR_PASSWORD
|
||||
psql -h localhost -U postgres -d mydb # no password prompt
|
||||
|
||||
# 5. Execute and exit
|
||||
psql -f script.sql dbname # execute file then exit
|
||||
psql -c "SELECT 1" dbname # run single command then exit
|
||||
psql -1 -f migration.sql dbname # run in single transaction
|
||||
|
||||
# 6. Service connection (reads from pg_service.conf)
|
||||
psql service=mydb_prod
|
||||
|
||||
# 7. Reconnect within a session
|
||||
\c dbname # reconnect to different db
|
||||
\c -reuse-previous=on sslmode=require # change only sslmode
|
||||
\c "host=newhost port=5432 dbname=mydb" # conninfo string
|
||||
```
|
||||
|
||||
On connection failure: interactive mode keeps the previous connection; script mode closes it and all subsequent database commands fail until the next successful `\c`.
|
||||
|
||||
Key flags: `-h` host, `-p` port, `-U` user, `-d` database, `-w` no password prompt, `-W` force password prompt, `-1` single transaction, `-f` execute file, `-c` execute command, `-t` tuples only, `-x` expanded, `-A` unaligned, `-E` echo hidden queries (`\d` internals), `-L` log file, `-X` skip `~/.psqlrc`.
|
||||
|
||||
**Connection precedence**: CLI flags > environment variables > `pg_service.conf` > defaults. **Password precedence**: connection string/password flag > `PGPASSWORD` env > `~/.pgpass`. Use `~/.pgpass` instead of `PGPASSWORD` in production — `PGPASSWORD` is visible in process listings (`ps aux`).
|
||||
|
||||
### Object Inspection (\d family)
|
||||
|
||||
| Command | Shows |
|
||||
| ----------------- | ----------------------------------------------------------------------------------------------------- |
|
||||
| `\d` | All tables, views, materialized views, sequences, foreign tables (equiv.`\dtvmsE`) |
|
||||
| `\dP` | Partitioned tables |
|
||||
| `\dt` | Tables only |
|
||||
| `\dv` | Views only |
|
||||
| `\di` | Indexes only |
|
||||
| `\ds` | Sequences only |
|
||||
| `\dm` | Materialized views only |
|
||||
| `\det` | Foreign tables (mnemonic: "external tables") |
|
||||
| `\dT` | Data types |
|
||||
| `\df` | Functions (use modifiers:`a`=aggregate, `n`=normal, `p`=procedure, `t`=trigger, `w`=window) |
|
||||
| `\da` | Aggregate functions |
|
||||
| `\dn` | Schemas |
|
||||
| `\du` / `\dg` | Roles |
|
||||
| `\db` | Tablespaces |
|
||||
| `\dc` | Conversions |
|
||||
| `\dD` | Domains |
|
||||
| `\dl` | Large objects (alias for `\lo_list`) |
|
||||
| `\dF` | Text search configurations |
|
||||
| `\dFd` | Text search dictionaries |
|
||||
| `\dFp` | Text search parsers |
|
||||
| `\dFt` | Text search templates |
|
||||
| `\des` | Foreign servers |
|
||||
| `\deu` | User mappings |
|
||||
| `\dew` | Foreign-data wrappers |
|
||||
| `\dp` | Privileges (GRANT/REVOKE) |
|
||||
| `\drds` | Per-role and per-database configuration settings |
|
||||
| `\l` | List databases (accepts pattern:`\l test*`) |
|
||||
|
||||
| `\dA` | Access methods |
|
||||
| `\dAc` / `\dAf` / `\dAo` / `\dAp` | Operator classes, families, operators, support functions |
|
||||
| `\dC` | Type casts |
|
||||
| `\dconfig` | Server configuration parameters (`\dconfig *` for all, PostgreSQL 16+) |
|
||||
| `\dd` | Object descriptions (comments) |
|
||||
| `\ddp` | Default privileges |
|
||||
| `\dL` | Procedural languages |
|
||||
| `\do` | Operators (accepts arg type patterns) |
|
||||
| `\dO` | Collations |
|
||||
| `\dP[itn]` | Partitioned tables (`t`=tables, `i`=indexes, `n`=nested) |
|
||||
| `\drg` | Granted role memberships |
|
||||
| `\dRp` / `\dRs` | Replication publications / subscriptions |
|
||||
| `\dX` | Extended statistics |
|
||||
| `\dx` | Installed extensions |
|
||||
| `\dy` | Event triggers |
|
||||
| `\sf[+]` | Show function definition |
|
||||
| `\sv[+]` | Show view definition |
|
||||
| `\z` | Privileges (alias for `\dp`) |
|
||||
|
||||
**Modifiers** (append to most `\d` commands):
|
||||
|
||||
- `+` — extra info (size, description): `\dt+`, `\l+`, `\du+`
|
||||
- `S` — include system objects: `\dtS`, `\dfS+`
|
||||
- `x` — expanded display mode: `\dt+x` (note: `\dx` is a different command; `x` must follow `S` or `+`)
|
||||
|
||||
Provide a name for details: `\d table_name` shows columns, types, indexes, constraints, foreign keys.
|
||||
|
||||
**Pattern matching** in \d commands:
|
||||
|
||||
- `*` = any sequence of characters, `?` = single character
|
||||
- `.` separates schema from object: `\dt public.*` or `\dt my_schema.users`
|
||||
- `..` separates database.schema.object: `\dt mydb.public.*` (db must match current db)
|
||||
- Double quotes stop case folding and wildcard expansion: `\dt "FOO"` matches `FOO` not `foo`
|
||||
- `$` is matched literally (not regex anchor)
|
||||
- Regex chars like `[0-9]` work: `\dt user[0-9]*` matches `user1`, `user2`
|
||||
- No pattern: shows all objects visible in current `search_path` (not all objects in DB)
|
||||
- Use `*.*` to see all objects in all schemas regardless of visibility
|
||||
|
||||
### Query Execution
|
||||
|
||||
| Command | Action |
|
||||
| ------------------------------------- | -------------------------------------------------------------------------------------- |
|
||||
| `;` | Execute the current query buffer |
|
||||
| `\g` | Execute (like `;`, but can add options) |
|
||||
| `\gx` | Execute with expanded output (like `\g`, forces `\x on`) |
|
||||
| `\g filename` | Execute and send output to file |
|
||||
| `\g \| command` | Execute and pipe output to shell command |
|
||||
| `\g (format=csv footer=off) file` | Execute with one-shot formatting options |
|
||||
| `\gdesc` | Describe result columns without executing |
|
||||
| `\gset [prefix]` | Execute and store results in psql variables |
|
||||
| `\gexec` | Execute each cell of result as a SQL command |
|
||||
| `\crosstabview` | Display result as crosstab (pivot table) |
|
||||
| `\watch` | Re-execute query periodically (see below) |
|
||||
| `\bind [params...]` | Use extended query protocol with parameters. Works with `\g`, `\gx`, and `\gset` |
|
||||
| `\bind_named stmt_name [params...]` | Bind named prepared statement |
|
||||
| `\parse stmt_name` | Create prepared statement from current query buffer |
|
||||
| `\close_prepared stmt_name` | Close a prepared statement |
|
||||
| `\;` | Append semicolon to buffer without executing |
|
||||
|
||||
### Data Import/Export
|
||||
|
||||
```sql
|
||||
-- Server-side (requires superuser for file access, uses server filesystem)
|
||||
COPY table TO '/path/file.csv' WITH (FORMAT csv, HEADER true);
|
||||
COPY table FROM '/path/file.csv' WITH (FORMAT csv, HEADER true);
|
||||
|
||||
-- Client-side (runs with client permissions, no superuser needed) — preferred
|
||||
\copy table TO '/path/file.csv' WITH (FORMAT csv, HEADER true)
|
||||
\copy table FROM '/path/file.csv' WITH (FORMAT csv, HEADER true)
|
||||
\copy (SELECT ...) TO '/path/output.csv' WITH (FORMAT csv, HEADER true)
|
||||
|
||||
-- Advanced: specific columns, NULL handling, custom delimiter
|
||||
\copy table (col1, col2) FROM 'data.csv' WITH (FORMAT csv, HEADER true, NULL 'N/A')
|
||||
```
|
||||
|
||||
`\copy` is the go-to for day-to-day work — it uses the client's filesystem and permissions, not the server's.
|
||||
|
||||
**\copy syntax detail:**
|
||||
|
||||
```
|
||||
-- FROM (import): sources are 'filename', program 'command', stdin, pstdin
|
||||
\copy table FROM 'file.csv' WITH (FORMAT csv, HEADER true) [ WHERE condition ]
|
||||
|
||||
-- TO (export): destinations are 'filename', program 'command', stdout, pstdout
|
||||
\copy table TO 'file.csv' WITH (FORMAT csv, HEADER true)
|
||||
```
|
||||
|
||||
For `\copy ... FROM stdin`, data rows continue until a line containing only `\.` is read or EOF is reached. Use `pstdin`/`pstdout` to always read/write psql's actual stdin/stdout regardless of `\o` setting.
|
||||
|
||||
WARNING: The `program` option executes a shell command. If constructed from user input, it can lead to command injection. Avoid string concatenation with untrusted data.
|
||||
|
||||
**Tip**: `\copy` takes the entire rest of the line as arguments (no variable interpolation). When you need variable interpolation or multi-line queries, use SQL `COPY ... TO STDOUT` with `\g` instead:
|
||||
|
||||
```sql
|
||||
-- This allows variable interpolation and multi-line queries
|
||||
COPY (SELECT * FROM :table WHERE id > :min_id) TO STDOUT WITH (FORMAT csv, HEADER true) \g /tmp/output.csv
|
||||
```
|
||||
|
||||
### Output Formatting
|
||||
|
||||
```
|
||||
\a Toggle aligned/unaligned output
|
||||
\x Toggle expanded display (vertical vs table)
|
||||
\t Toggle tuples only (no headers/footers)
|
||||
\pset format FORMAT Set output format: aligned, asciidoc, csv, html, latex, latex-longtable, troff-ms, unaligned, wrapped
|
||||
\pset border N Set border style (0-2; 3 for latex data-row lines)
|
||||
\pset null STRING Display NULL as STRING
|
||||
\pset pager [off] Control pager usage
|
||||
\pset title 'TEXT' Set table title
|
||||
\pset recordsep SEP Set record separator for unaligned mode
|
||||
\pset fieldsep SEP Set field separator for unaligned mode (default: |)
|
||||
\pset footer [on|off] Toggle row count footer
|
||||
\pset columns N Set target width for wrapped format
|
||||
\pset csv_fieldsep C Set CSV field separator (default: comma)
|
||||
\pset numericlocale [on|off] Toggle locale-specific number formatting
|
||||
\pset linestyle STYLE Set border style: ascii, old-ascii, unicode
|
||||
\pset pager_min_lines N Minimum lines before pager activates
|
||||
\pset xheader_width MODE Expanded header width: full, column, page, or N (PostgreSQL 17+)
|
||||
\H Toggle HTML output (shortcut)
|
||||
\C [title] Set table title (shortcut for \pset title)
|
||||
\f [string] Set field separator (shortcut for \pset fieldsep)
|
||||
\T table_options Set HTML table attributes (shortcut for \pset tableattr)
|
||||
```
|
||||
|
||||
### Large Objects
|
||||
|
||||
```
|
||||
\lo_import filename [comment] Import file as large object, returns OID
|
||||
\lo_export loid filename Export large object to file
|
||||
\lo_list[x+] List all large objects
|
||||
\lo_unlink loid Delete large object
|
||||
```
|
||||
|
||||
Large object OIDs are persistent references. Always associate a human-readable comment on import. Use `\lo_list` to find OIDs.
|
||||
|
||||
### Scripting & Control Flow
|
||||
|
||||
```
|
||||
\i filename Execute file (relative to current working directory)
|
||||
\ir filename Execute file (relative to the script being processed)
|
||||
\o [filename] Redirect query output to file (or pipe with |cmd)
|
||||
\o Stop output redirection
|
||||
\qecho TEXT Output text to redirected output
|
||||
\echo TEXT Output text to stdout (-n suppresses trailing newline)
|
||||
\warn TEXT Output text to stderr
|
||||
\! command Execute shell command
|
||||
\cd [dir] Change working directory
|
||||
\set NAME VALUE Set psql variable
|
||||
\unset NAME Unset psql variable
|
||||
\prompt [TEXT] NAME Prompt user for variable value
|
||||
\getenv psql_var env_var Copy environment variable into psql variable
|
||||
\setenv name [value] Set or unset environment variable
|
||||
\p Print current query buffer
|
||||
\w filename Write query buffer to file (or pipe with |cmd)
|
||||
|
||||
-- Conditional execution (useful in scripts)
|
||||
\if EXPR
|
||||
\echo 'true branch'
|
||||
\else
|
||||
\echo 'false branch'
|
||||
\endif
|
||||
|
||||
\elif EXPR Else-if inside \if block
|
||||
```
|
||||
|
||||
`\if` and `\elif` evaluate their argument as a boolean. Valid values (case-insensitive, unambiguous prefix matching): `true`, `false`, `1`, `0`, `on`, `off`, `yes`, `no`. Expressions that don't evaluate to true/false generate a warning and are treated as false. Variable references in skipped lines are NOT expanded.
|
||||
|
||||
Variables in SQL: `:'varname'` (quoted string value, escapes embedded quotes), `:"varname"` (double-quoted identifier), `:'varname'::type` (with cast), `:varname` (unquoted — can break SQL), `:{?varname}` (tests existence, expands to TRUE/FALSE).
|
||||
|
||||
### Session Management
|
||||
|
||||
```
|
||||
\c [dbname [user]] Connect to database (or reconnect)
|
||||
\conninfo Display connection info (includes SSL info)
|
||||
\encoding [ENC] Set or show client encoding
|
||||
\password [USER] Change password (does NOT appear in command history or server log)
|
||||
\q Quit psql. In a script file, only that script is terminated. In interactive mode, the entire program exits.
|
||||
\r Reset (clear) the query buffer
|
||||
\e Edit query buffer in external editor
|
||||
\ef [FUNCNAME] Edit function definition
|
||||
\ev [VIEWNAME] Edit view definition
|
||||
\sf[+] FUNCNAME Show function definition (read-only)
|
||||
\sv[+] VIEWNAME Show view definition (read-only)
|
||||
\s [FILE] Print command history (or save to file)
|
||||
\restrict KEY Enter restricted mode (only \unrestrict allowed)
|
||||
\unrestrict KEY Exit restricted mode
|
||||
\timing [on\|off] Toggle query execution time display (milliseconds)
|
||||
\errverbose Repeat last error at maximum verbosity
|
||||
\? [topic] Help: commands, options, or variables
|
||||
\h [command] SQL syntax help (use * for all: \h *)
|
||||
\copyright Show PostgreSQL copyright
|
||||
```
|
||||
|
||||
### Pipeline Mode (PostgreSQL 14+)
|
||||
|
||||
```
|
||||
\startpipeline
|
||||
SELECT $1 \bind 42 \sendpipeline
|
||||
SELECT $1 \bind 100 \sendpipeline
|
||||
\getresults
|
||||
\endpipeline
|
||||
```
|
||||
|
||||
Pipeline mode sends multiple queries without waiting for each result, reducing round-trip latency. All queries use the extended query protocol.
|
||||
|
||||
**Pipeline commands:**
|
||||
|
||||
- `\startpipeline` — begin pipeline block
|
||||
- `\endpipeline` — end pipeline block and process remaining results
|
||||
- `\sendpipeline` — append current query buffer to pipeline without waiting
|
||||
- `\syncpipeline` — send sync message without ending pipeline
|
||||
- `\flushrequest` — request server flush without sync
|
||||
- `\flush` — manually push unsent data to server
|
||||
- `\getresults [N]` — read pending results (N=0 or omitted means all)
|
||||
|
||||
**Pipeline limitations:**
|
||||
|
||||
- `COPY` is not supported in pipeline mode
|
||||
- Meta-commands like `\g`, `\gx`, `\gdesc` are not allowed inside a pipeline
|
||||
- All queries use the extended query protocol
|
||||
- Use `\bind`, `\bind_named`, `\parse`, `\close_prepared`, or `\sendpipeline` within pipelines
|
||||
- A `%P` prompt variable shows pipeline status (`on`, `off`, or `abort`)
|
||||
|
||||
### \watch Syntax
|
||||
|
||||
```
|
||||
\watch [i[nterval]=SECONDS] [c[ount]=TIMES] [m[in_rows]=ROWS] [SECONDS]
|
||||
```
|
||||
|
||||
`count` and `min_rows` require PostgreSQL 17+.
|
||||
|
||||
- `interval` — seconds between executions (default: 2, overridable via `WATCH_INTERVAL` variable)
|
||||
- `count` — stop after N executions
|
||||
- `min_rows` — stop if query returns fewer than N rows
|
||||
|
||||
If the query buffer is empty, `\watch` re-executes the most recently sent query.
|
||||
|
||||
Examples:
|
||||
|
||||
```sql
|
||||
SELECT * FROM pg_stat_activity WHERE state = 'active';
|
||||
\watch interval=5 count=10 -- every 5s, stop after 10 runs
|
||||
|
||||
SELECT count(*) FROM queue WHERE status = 'pending';
|
||||
\watch i=1 min_rows=1 -- every 1s, stop when queue is empty
|
||||
```
|
||||
|
||||
### Exit Codes
|
||||
|
||||
| Code | Meaning |
|
||||
| ---- | --------------------------------------------------------------- |
|
||||
| 0 | Successful completion |
|
||||
| 1 | A fatal error occurred (server error, connection failure, etc.) |
|
||||
| 2 | Connection failed (could not connect to the server) |
|
||||
| 3 | Script execution ended due to ON_ERROR_STOP |
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### Destructive Operations Checklist
|
||||
|
||||
Before running any destructive SQL, verify impact first:
|
||||
|
||||
```sql
|
||||
-- BEFORE DELETE: check how many rows are affected
|
||||
SELECT count(*) FROM users WHERE condition; -- verify scope
|
||||
BEGIN;
|
||||
DELETE FROM users WHERE condition RETURNING *; -- see what was deleted
|
||||
-- ROLLBACK if wrong; COMMIT only after verification
|
||||
|
||||
-- BEFORE DROP TABLE: verify no foreign keys depend on it
|
||||
\d table_name -- check "Referenced by" section
|
||||
-- Consider renaming first: ALTER TABLE old RENAME TO old_backup;
|
||||
```
|
||||
|
||||
### Dangerous Commands Requiring Extra Caution
|
||||
|
||||
| Command/Pattern | Risk | Mitigation |
|
||||
| --------------------------------------- | --------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
|
||||
| `\gexec` | Executes generated SQL without confirmation | Always inspect the generating query first by running it without `\gexec`; set `ON_ERROR_STOP on` |
|
||||
| `\! command` | Arbitrary shell execution | No sandboxing; commands run with psql user's full privileges |
|
||||
| `\copy ... program 'cmd'` | Shell command injection if filename comes from user input | Never concatenate untrusted input into the `program` string |
|
||||
| `\deu+` | May display remote user passwords | Avoid using `\deu+` in shared/piped output; use `\deu` without `+` |
|
||||
| `DELETE`/`UPDATE` without `WHERE` | Affects every row in the table | Always use `WHERE`; wrap in `BEGIN`/`ROLLBACK` to preview |
|
||||
| `DROP DATABASE/TABLE` | Irreversible data loss | Verify you're on the correct database with `\conninfo` first |
|
||||
|
||||
### Variable Interpolation Safety
|
||||
|
||||
psql variables are **plain text substitution**, not parameterized queries. This means:
|
||||
|
||||
```sql
|
||||
-- UNSAFE: if :name contains "Robert'); DROP TABLE users;--" it will execute the injection
|
||||
SELECT * FROM users WHERE name = :'name';
|
||||
|
||||
-- SAFER: use \prompt for interactive input (user sees what they typed)
|
||||
\prompt 'Enter name: ' search_name
|
||||
SELECT * FROM users WHERE name = :'search_name';
|
||||
|
||||
-- SAFEST: use \bind for programmatic parameter passing (truly parameterized)
|
||||
SELECT * FROM users WHERE name = $1;
|
||||
\bind 'Robert' \g
|
||||
```
|
||||
|
||||
The `:'varname'` form (quoted) is always safer than `:varname` (unquoted), because unquoted substitution can break SQL syntax or enable injection. Use `:"varname"` for identifiers (table/column names) — it properly escapes embedded double quotes.
|
||||
|
||||
## When to Use What
|
||||
|
||||
| Scenario | Recommended Command |
|
||||
| ----------------------------- | -------------------------------------------------------------- |
|
||||
| Quick table inspection | `\d table_name` |
|
||||
| List all tables in schema | `\dt schema.*` |
|
||||
| Check indexes on a table | `\di+ table_name*` or `\d table_name` |
|
||||
| Export query to CSV | `\copy (SELECT ...) TO 'file.csv' WITH (FORMAT csv, HEADER)` |
|
||||
| Import CSV into table | `\copy table FROM 'file.csv' WITH (FORMAT csv, HEADER)` |
|
||||
| Run migration script | `psql -1 -f migration.sql dbname` |
|
||||
| Watch a live query | `SELECT ... \watch 5` |
|
||||
| Pivot query results | `SELECT ... \crosstabview` |
|
||||
| Script with conditional logic | `\if :var ... \endif` |
|
||||
| Batch-insert many rows | Use `\startpipeline` / `\endpipeline` |
|
||||
| SQL syntax help | `\h CREATE TABLE` |
|
||||
| psql command help | `\? commands` |
|
||||
| Check query execution time | `\timing on` then run query |
|
||||
| Debug error details | `\errverbose` |
|
||||
| Handle large result sets | `\set FETCH_COUNT 1000` then run query |
|
||||
| Auto-savepoint on errors | `\set ON_ERROR_ROLLBACK on` then use transactions |
|
||||
|
||||
- **`references/meta-commands-core.md`** — Core meta-commands: query buffer behavior, argument parsing rules, connection management, query execution, `\copy` syntax, and scripting commands (`\if`, `\i`, `\o`, backquote expansion). Read this when you need exact syntax or behavioral details for any backslash command.
|
||||
- **`references/meta-commands-inspection.md`** — Full `\d` command reference: all object inspection commands, modifiers (`S`, `+`, `x`), and pattern matching rules. Read this when exploring database schema or when the user needs to inspect tables, indexes, views, functions, privileges, etc.
|
||||
- **`references/meta-commands-formatting.md`** — Output formatting (`\pset` options and all format descriptions), pipeline mode, `\watch`, `\crosstabview`, and session management (`\e`, `\ef`, `\ev`, `\timing`, etc.). Read this when the user needs to control output format or use pipeline mode.
|
||||
- **`references/cli-options-and-variables.md`** — All CLI flags, environment variables, psql internal variables (AUTOCOMMIT, ON_ERROR_STOP, ECHO, FETCH_COUNT, etc.), prompt customization, `~/.psqlrc` configuration, and SQL interpolation syntax. Read this when configuring psql startup behavior, writing scripts that depend on variable state, or customizing prompts.
|
||||
- **`references/tips-workflows.md`** — Practical workflows (exploring a new database, understanding table structure), scripting patterns (safe scripts, conditional execution, `\gexec`), output control for automation, and data import/export patterns. Read this when the user asks how to accomplish a specific task with psql.
|
||||
- **`references/tips-advanced.md`** — Performance tips, debugging/introspection (`EXPLAIN`, lock analysis, `ECHO_HIDDEN`), safety best practices (ON_ERROR_STOP, transaction patterns, search_path safety), and common gotchas. Read this for lock analysis, query plan inspection, and troubleshooting.
|
||||
|
||||
## Important Notes
|
||||
|
||||
psql handles two comment styles differently:
|
||||
|
||||
- **C-style block comments** (`/* ... */`): Passed to the server for processing and removal.
|
||||
- **SQL-standard comments** (`--`): Removed by psql itself, before sending to the server.
|
||||
|
||||
This distinction matters when writing scripts that rely on comment behavior — only SQL-standard comments are stripped client-side.
|
||||
|
||||
### Variable Variables (Soft References)
|
||||
|
||||
psql allows indirect variable references through `\set`:
|
||||
|
||||
```sql
|
||||
\set foo 'my_table'
|
||||
\set bar :foo -- copies the value of foo into bar
|
||||
\echo :bar -- outputs: my_table
|
||||
```
|
||||
|
||||
While constructs like `\set :foo 'something'` are syntactically valid, they produce "soft links" that have limited practical use. For straightforward variable copying, use `\set new_var :old_var`.
|
||||
|
||||
### Version Compatibility
|
||||
|
||||
psql works best with servers of the same or an older major version. Backslash commands (especially `\d` family) may fail with newer server versions. When connecting to multiple server versions, use the newest available psql client. The `\d` commands generally work with servers back to version 9.2.
|
||||
|
||||
## External References
|
||||
|
||||
- [PostgreSQL Client Applications](https://www.postgresql.org/docs/current/app-psql.html)
|
||||
- [Official PostgreSQL Documentation](https://www.postgresql.org/docs/current/index.html)
|
||||
- [The SQL Language](https://www.postgresql.org/docs/current/sql.html)
|
||||
- [SQL Syntax - The SQL Language](https://www.postgresql.org/docs/current/sql-syntax.html)
|
||||
- [SQL Command](https://www.postgresql.org/docs/current/sql-commands.html)
|
||||
- [PostgreSQL Wiki](https://wiki.postgresql.org/)
|
||||
|
||||
## Limitations
|
||||
|
||||
- Use this skill only when the task clearly matches its upstream source and local project context.
|
||||
- Verify commands, generated code, dependencies, credentials, and external service behavior before applying changes.
|
||||
- Do not treat examples as a substitute for environment-specific tests, security review, or user approval for destructive or costly actions.
|
||||
+444
@@ -0,0 +1,444 @@
|
||||
# psql CLI Options, Variables & Environment
|
||||
|
||||
Complete reference for psql command-line flags, configuration variables, and environment variables.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [CLI Options](#cli-options)
|
||||
- [Connection Parameters](#connection-parameters)
|
||||
- [Input/Output Options](#inputoutput-options)
|
||||
- [Output Format Options](#output-format-options)
|
||||
- [psql Variables](#psql-variables)
|
||||
- [Environment Variables](#environment-variables)
|
||||
- [Configuration Files](#configuration-files)
|
||||
- [Tab Completion](#tab-completion)
|
||||
- [Editor Integration](#editor-integration)
|
||||
|
||||
---
|
||||
|
||||
## CLI Options
|
||||
|
||||
### Synopsis
|
||||
|
||||
```
|
||||
psql [option...] [dbname [user]]
|
||||
```
|
||||
|
||||
When `dbname` is the first non-option argument, it specifies the database. The second non-option argument specifies the user.
|
||||
|
||||
### General Options
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `-a` / `--echo-all` | Print all nonempty input lines to stdout as they are read. Equivalent to `ECHO=all`. |
|
||||
| `-b` / `--echo-errors` | Print failed SQL commands to stderr. Equivalent to `ECHO=errors`. |
|
||||
| `-c command` / `--command=command` | Execute one or more SQL commands, then exit. Commands can be separated by semicolons. Each `-c` string is sent as a single request — multiple SQL commands within it execute in one transaction (unless explicit `BEGIN`/`COMMIT`). Cannot mix SQL and meta-commands in one `-c`. Returns 0 on success, 1 on error, 2 if connection fails. |
|
||||
| `-d dbname` / `--dbname=dbname` | Database name to connect to |
|
||||
| `-e` / `--echo-queries` | Copy all SQL commands sent to the server to standard output as well |
|
||||
| `-E` / `--echo-hidden` | Echo hidden queries (the SQL generated by \d commands and other meta-commands) to stderr. Useful for learning how psql works internally. |
|
||||
| `-f filename` / `--file=filename` | Execute commands from file, then exit. Use `-` for stdin (reads until EOF or `\q`; Readline not available). `-f` provides line-numbered error messages unlike shell redirection. |
|
||||
| `-F separator` / `--field-separator=separator` | Field separator for unaligned output (default: `|`) |
|
||||
| `-H` / `--html` | HTML output mode |
|
||||
| `-l` / `--list` | List available databases, then exit. Connects to `postgres` database unless a different database is specified via `-d` or a non-option argument. |
|
||||
| `-L filename` / `--log-file=filename` | Log all session output to file |
|
||||
| `-n` / `--no-readline` | Disable enhanced command-line editing and tab completion |
|
||||
| `-o filename` / `--output=filename` | Redirect all query output to file |
|
||||
| `-P assignment` / `--pset=assignment` | Set printing option (format: `option=value`) |
|
||||
| `-q` / `--quiet` | Quiet mode — no startup message, no informational messages |
|
||||
| `-R separator` / `--record-separator=separator` | Record separator for unaligned output (default: newline) |
|
||||
| `-s` / `--single-step` | Single-step mode. Confirm before each command is sent to the server. |
|
||||
| `-S` / `--single-line` | Single-line mode. Newline terminates a query (as if semicolon). Not recommended — execution order can be unclear when mixing SQL and meta-commands on the same line. |
|
||||
| `-t` / `--tuples-only` | Print rows only — no headers, footers |
|
||||
| `-T table_options` / `--table-attr=table_options` | HTML table attributes |
|
||||
| `-v assignment` / `--set=assignment` / `--variable=assignment` | Set psql variable (format: `name=value` sets, `name` unsets, `name=` sets to empty). Assignment happens at command-line processing time, so connection-state variables are overwritten later. |
|
||||
| `-V` / `--version` | Print psql version and exit |
|
||||
| `-w` / `--no-password` | Never issue a password prompt. Fails if password is required. Setting persists for the entire session, including `\connect` attempts. |
|
||||
| `-W` / `--password` | Force password prompt. Setting persists for the entire session, including `\connect` attempts. |
|
||||
| `-x` / `--expanded` | Turn on expanded table output |
|
||||
| `-X` / `--no-psqlrc` | Do not read the startup file (~/.psqlrc) |
|
||||
| `-z` / `--field-separator-zero` | Set field separator to NUL byte |
|
||||
| `-0` / `--record-separator-zero` | Set record separator to NUL byte |
|
||||
| `-1` / `--single-transaction` | Wrap `-f` or `-c` commands in a single transaction. If any command fails, all roll back. Warning: if the script itself contains `BEGIN`/`COMMIT`/`ROLLBACK`, this option will not have the expected effect. |
|
||||
| `-?` / `--help[=topic]` | Show help. `topic` can be `commands` (backslash commands), `options` (CLI options, default), or `variables` (config variables). |
|
||||
| `--csv` | Switch to CSV output mode. Equivalent to `\pset format csv`. |
|
||||
|
||||
---
|
||||
|
||||
## Connection Parameters
|
||||
|
||||
These options control how psql connects to PostgreSQL.
|
||||
|
||||
| Flag | Env Variable | Description |
|
||||
|------|-------------|-------------|
|
||||
| `-h host` | `PGHOST` | Host name or socket directory (default: local socket) |
|
||||
| `-p port` | `PGPORT` | Port number (default: 5432) |
|
||||
| `-U user` | `PGUSER` | Database user name |
|
||||
| `-d dbname` | `PGDATABASE` | Database name |
|
||||
| `-w` | — | Don't prompt for password |
|
||||
| `-W` | — | Force password prompt |
|
||||
|
||||
**Connection URI:**
|
||||
```
|
||||
psql postgresql://user:password@host:5432/dbname?sslmode=require
|
||||
psql postgresql:///dbname?host=/var/run/postgresql
|
||||
```
|
||||
|
||||
**Service lookup:** If `PGSERVICE` or `service=name` in connection string is set, psql reads connection parameters from `pg_service.conf`.
|
||||
|
||||
---
|
||||
|
||||
## Input/Output Options
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `-c command` | Execute command(s) then exit. Multiple commands separated by `;`. |
|
||||
| `-f filename` | Read commands from file then exit. Use `-` for stdin. |
|
||||
| `-1` | Run in a single transaction (only effective with `-c` or `-f`) |
|
||||
| `-a` | Echo all input lines to stdout |
|
||||
| `-b` | Echo failed SQL to stderr |
|
||||
| `-e` | Echo queries to stdout |
|
||||
| `-E` | Echo hidden queries (\d internals) to stderr |
|
||||
| `-L file` | Log all output to file |
|
||||
| `-o file` | Redirect output to file |
|
||||
| `-n` | Disable readline |
|
||||
|
||||
**Common patterns:**
|
||||
```bash
|
||||
# Run a migration in a transaction
|
||||
psql -1 -f migration.sql mydb
|
||||
|
||||
# Execute a single query
|
||||
psql -c "SELECT count(*) FROM users" mydb
|
||||
|
||||
# Pass a variable from the command line
|
||||
psql -v table=users -c 'SELECT count(*) FROM :"table"' mydb
|
||||
|
||||
# Batch process with for-loop
|
||||
for f in /tmp/*.sql; do psql -1 -f "$f" mydb; done
|
||||
|
||||
# Echo internal queries to learn psql
|
||||
psql -E mydb -c "\d+ users"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Output Format Options
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `-A` / `--no-align` | Unaligned (delimiter-separated) output |
|
||||
| `-F sep` | Field separator (default: `|`) |
|
||||
| `-H` / `--html` | HTML table output |
|
||||
| `-P opt=val` | Set pset option (e.g., `-P pager=off`) |
|
||||
| `-R sep` | Record separator (default: newline) |
|
||||
| `-t` | Tuples only (no headers/footers) |
|
||||
| `-T attrs` | HTML table attributes |
|
||||
| `-x` | Expanded display |
|
||||
| `-z` / `-0` | NUL separators |
|
||||
|
||||
**Script-friendly output pattern:**
|
||||
```bash
|
||||
# CSV output
|
||||
psql --csv -c "SELECT id, name FROM users" mydb
|
||||
|
||||
# Custom delimiter output
|
||||
psql -A -F ',' -t -c "SELECT id, name FROM users" mydb
|
||||
|
||||
# NUL-separated for xargs -0
|
||||
psql -A -z -t -c "SELECT filename FROM files_to_process" mydb | xargs -0 process
|
||||
|
||||
# JSON-friendly (one value per line)
|
||||
psql -A -t -c "SELECT json_agg(row_to_json(t)) FROM (SELECT id, name FROM users) t" mydb
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## psql Variables
|
||||
|
||||
psql maintains internal variables that control behavior. Set with `\set`, unset with `\unset`, view all with `\set` (no arguments).
|
||||
|
||||
### Automatic Variables
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `AUTOCOMMIT` | `on` (default) or `off`. When off, psql auto-issues implicit `BEGIN` before any command not in a transaction block (except `BEGIN`/`VACUUM` etc.). You must explicitly `COMMIT` or `ROLLBACK`. |
|
||||
| `COMP_KEYWORD_CASE` | `lower`, `upper`, `preserve-lower` (default), `preserve-upper`. Controls tab-completion keyword casing. `preserve-lower`/`preserve-upper` preserves case of already-typed input; empty input completes as lower/upper case. |
|
||||
| `DBNAME` | Current database name. Set automatically on connect. |
|
||||
| `ECHO` | `none` (default), `all`, `queries`, `errors`. Controls what gets echoed. `all` echoes all commands (including scripts). `queries` echoes only SQL queries, not meta-commands. `errors` echoes failed SQL commands to stderr (set by `-b`). |
|
||||
| `ECHO_HIDDEN` | `off`, `on`, `noexec`. When `on`, shows hidden queries (SQL behind \d commands). `noexec` shows them without executing. |
|
||||
| `ENCODING` | Current client encoding. Set automatically. |
|
||||
| `ERROR` | `true` if the last query failed, `false` otherwise. |
|
||||
| `FETCH_COUNT` | Integer (default: 0). When set, psql fetches rows in batches of this size instead of all at once. Useful for large result sets. |
|
||||
| `HIDE_TABLEAM` | If set, hide table access methods in `\d+` output. |
|
||||
| `HIDE_TOAST_COMPRESSION` | If set, hide compression method in `\d+` output. |
|
||||
| `HISTCONTROL` | `none` (default), `ignorespace`, `ignoredups`, `ignoreboth`. Controls history saving. |
|
||||
| `HISTFILE` | Path to history file (default: `~/.psql_history`). Can include psql variable references, e.g. `\set HISTFILE ~/.psql_history-:DBNAME`. |
|
||||
| `HISTSIZE` | Maximum number of history entries (default: 500). A negative value disables the limit. |
|
||||
| `HOST` | Current server host. Set automatically on connect. |
|
||||
| `IGNOREEOF` | If set, prevents Ctrl-D from exiting. Value is the number of EOFs to ignore before quitting. |
|
||||
| `LAST_ERROR_MESSAGE` | Error message from the last failed query. |
|
||||
| `LAST_ERROR_SQLSTATE` | SQLSTATE error code from the last failed query (`00000` if no error). |
|
||||
| `LASTOID` | OID of the last affected row by `INSERT` or `\lo_import`. Always 0 for PG 12+ tables (OID column removed). |
|
||||
| `ON_ERROR_ROLLBACK` | `off` (default), `on`, `interactive`. When `on`, errors inside a transaction create savepoints automatically, allowing continued execution. `interactive` only activates in interactive sessions, not when reading scripts. |
|
||||
| `ON_ERROR_STOP` | `off` (default) or `on`. When `on`, a query error or meta-command error stops script execution and exits. Critical for safe scripting. |
|
||||
| `PIPELINE_COMMAND_COUNT` | Number of queued commands in current pipeline. |
|
||||
| `PIPELINE_RESULT_COUNT` | Number of commands with pending results in current pipeline. |
|
||||
| `PIPELINE_SYNC_COUNT` | Number of queued sync messages in current pipeline. |
|
||||
| `PORT` | Current server port. Set automatically on connect. |
|
||||
| `PROMPT1`, `PROMPT2`, `PROMPT3` | Prompt format strings (see below). |
|
||||
| `QUIET` | `on` or `off`. Quiet mode. |
|
||||
| `ROW_COUNT` | Number of rows affected by the last query. |
|
||||
| `SERVER_VERSION_NAME` | Server version string. |
|
||||
| `SERVER_VERSION_NUM` | Server version as integer (e.g., 160000 for 16.0). |
|
||||
| `SERVICE` | Service name from the connection, if applicable. |
|
||||
| `SHELL_ERROR` | `true` if the last shell command (`\!`, `\g`, `\o`, `\w`, `\copy`, backquote) failed, `false` otherwise. |
|
||||
| `SHELL_EXIT_CODE` | Exit code of the last shell command (0-127 normal exit, 128-255 signal termination, -1 launch failure). |
|
||||
| `SHOW_ALL_RESULTS` | `on` (default) or `off`. When on, show all results from combined queries. |
|
||||
| `SHOW_CONTEXT` | `never`, `errors`, `always`. Controls display of `CONTEXT:` in messages. Default: `errors`. |
|
||||
| `SINGLELINE` | `on` or `off`. Newline acts as query terminator. |
|
||||
| `SINGLESTEP` | `on` or `off`. Confirm before each command. |
|
||||
| `SQLSTATE` | SQLSTATE error code from the last query. |
|
||||
| `USER` | Current database user. Set automatically on connect. |
|
||||
| `VERSION` | psql client full version string. |
|
||||
| `VERSION_NAME` | psql client short version (e.g., `18beta1`). |
|
||||
| `VERSION_NUM` | psql client version as integer (e.g., `180000`). |
|
||||
| `WATCH_INTERVAL` | Default interval (seconds) for `\watch` command (default: 2). |
|
||||
| `VERBOSITY` | `default`, `verbose`, `terse`, `sqlstate`. Controls error message detail level. |
|
||||
|
||||
### SQL Interpolation
|
||||
|
||||
psql variables can be interpolated into SQL statements using colon-prefixed syntax. This is **plain text substitution**, not parameterized queries — understand the differences to use it safely.
|
||||
|
||||
| Syntax | Behavior | Example |
|
||||
|--------|----------|---------|
|
||||
| `:varname` | Unquoted substitution. The variable's value replaces `:varname` literally, which can break SQL syntax or enable injection if the value contains special characters. | `\set table users` → `SELECT * FROM :table;` → `SELECT * FROM users;` |
|
||||
| `:'varname'` | Single-quoted string substitution. The value is placed inside single quotes, with any embedded single quotes and backslashes escaped. This is the safest form for values. | `\set name O'Brien` → `SELECT * FROM users WHERE name = :'name';` → `SELECT * FROM users WHERE name = 'O''Brien';` |
|
||||
| `:"varname"` | Double-quoted identifier substitution. The value is placed inside double quotes, with embedded double quotes doubled. Use this for table/column names. | `\set col first name` → `SELECT :"col" FROM users;` → `SELECT "first name" FROM users;` |
|
||||
| `:{?varname}` | Variable existence test. Always expands — `TRUE` if defined, `FALSE` otherwise. Designed for use in `\if` conditions. | `\if :{?myvar}` → true if `myvar` was set |
|
||||
| `\:varname` | Escaped colon. The colon is not treated as a variable reference — `:varname` is passed through literally. | `SELECT \:not_a_var FROM t;` → `SELECT :not_a_var FROM t;` |
|
||||
|
||||
Note: Variable interpolation does NOT occur inside quoted SQL literals or identifiers. Therefore `':foo'` does not produce a quoted string from the variable (and wouldn't be safe even if it did — it can't handle embedded quotes properly). Use `:'foo'` instead.
|
||||
|
||||
**Safety guidance**: Always prefer `:'varname'` (quoted string) over `:varname` (unquoted) when substituting user-provided values. Unquoted substitution can break SQL syntax or enable injection. For the safest programmatic parameter passing, use `\bind` with the extended query protocol (which provides true parameterized queries).
|
||||
|
||||
### Key Variables for Scripting
|
||||
|
||||
**ON_ERROR_STOP** — The most important variable for scripts. Set it in scripts to ensure they abort on the first error instead of continuing:
|
||||
|
||||
```
|
||||
-- At the top of any script:
|
||||
\set ON_ERROR_STOP on
|
||||
|
||||
-- Now any error stops execution
|
||||
INSERT INTO users (id) VALUES (1);
|
||||
INSERT INTO users (id) VALUES ('bad'); -- aborts here
|
||||
INSERT INTO users (id) VALUES (2); -- never reached
|
||||
```
|
||||
|
||||
**AUTOCOMMIT** — Turn off to manually manage transactions:
|
||||
|
||||
```
|
||||
\set AUTOCOMMIT off
|
||||
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
|
||||
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
|
||||
COMMIT;
|
||||
\set AUTOCOMMIT on
|
||||
```
|
||||
|
||||
**FETCH_COUNT** — For very large result sets that would consume too much memory:
|
||||
|
||||
```
|
||||
\set FETCH_COUNT 1000
|
||||
SELECT * FROM huge_table;
|
||||
```
|
||||
|
||||
**ERROR / SQLSTATE / LAST_ERROR_MESSAGE** — For conditional logic:
|
||||
|
||||
```
|
||||
INSERT INTO unique_table (id) VALUES (1);
|
||||
\if :ERROR
|
||||
\echo 'Insert failed: ' :LAST_ERROR_MESSAGE
|
||||
\else
|
||||
\echo 'Insert succeeded, rows affected: ' :ROW_COUNT
|
||||
\endif
|
||||
```
|
||||
|
||||
### Prompt Customization
|
||||
|
||||
`PROMPT1` is the normal prompt (default: `'%/%R%x%# '`). `PROMPT2` appears when a command is incomplete (continuation) (default: `'%/%R%x%# '`). `PROMPT3` appears during `COPY FROM STDIN` when row values are needed (default: `'>> '`).
|
||||
|
||||
**Format specifiers:**
|
||||
|
||||
| Spec | Output |
|
||||
|------|--------|
|
||||
| `%/` | Current database name |
|
||||
| `%~` | Like `%/` but `~` if the database is your default database |
|
||||
| `%m` | Host name (truncated at first dot), or `[local]` for Unix sockets |
|
||||
| `%M` | Full host name, `[local:/dir/name]` for non-default Unix sockets |
|
||||
| `%>` | Port number |
|
||||
| `%n` | User name |
|
||||
| `%s` | Service name (from connection) |
|
||||
| `%#` | `#` if superuser, `>` otherwise |
|
||||
| `%p` | Process ID of the server backend |
|
||||
| `%R` | PROMPT1: `=` normally, `^` in single-line mode, `@` if conditional stack inactive (e.g., inside skipped `\if`), `!` if not connected. PROMPT2: `-` (continuation), `*` (comment), `'` (single-quoted), `"` (double-quoted), `$` (dollar-quoted), `(` (parenthesized). PROMPT3: empty. |
|
||||
| `%w` | Whitespace matching the visible width of the last PROMPT1 output (for aligning PROMPT2) |
|
||||
| `%x` | Transaction status: empty (idle), `*` (in transaction block), `!` (failed transaction), `?` (unknown or no connection) |
|
||||
| `%l` | Line number inside the current statement, starting from 1 |
|
||||
| `%P` | Pipeline status: `on` (pipeline mode active), `off` (not in pipeline mode), `abort` (pipeline aborted) |
|
||||
| `%%` | Literal `%` |
|
||||
| `%` digits | Character with the given octal code (e.g., `%033` = ESC character) |
|
||||
| `%:varname:` | Value of psql variable |
|
||||
| `` %`[command]` `` | Output of shell command (trailing newline stripped) |
|
||||
| `%[ ... %]` | Tell Readline that the contained text is invisible (for ANSI escape codes) |
|
||||
|
||||
**Common prompt configurations:**
|
||||
```
|
||||
-- Show database and user
|
||||
\set PROMPT1 '%n@%m %/%R%# '
|
||||
|
||||
-- Show transaction status
|
||||
\set PROMPT1 '%/%x%# '
|
||||
|
||||
-- Production-safe prompt (color-coded)
|
||||
-- Note: %033 is octal for ESC character; %[...%] tells Readline these chars are invisible
|
||||
\set PROMPT1 '%[%033[1;31m%]%/%[%033[0m%]%R%# '
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `PGDATABASE` | Default database name |
|
||||
| `PGHOST` | Default host (or socket directory) |
|
||||
| `PGPORT` | Default port (5432) |
|
||||
| `PGUSER` | Default user |
|
||||
| `PGPASSWORD` | Password (not recommended — use `~/.pgpass` instead) |
|
||||
| `PGPASSFILE` | Path to password file (default: `~/.pgpass`) |
|
||||
| `PGSERVICE` | Service name from `pg_service.conf` |
|
||||
| `PGSERVICEFILE` | Path to service file |
|
||||
| `PGOPTIONS` | Default options to pass to the server |
|
||||
| `PGSSLMODE` | SSL mode (`disable`, `allow`, `prefer`, `require`, `verify-ca`, `verify-full`) |
|
||||
| `PGREQUIRESSL` | Legacy SSL flag (use `PGSSLMODE` instead) |
|
||||
| `PGSSLCERT` | Client certificate path |
|
||||
| `PGSSLKEY` | Client key path |
|
||||
| `PGSSLROOTCERT` | Root certificate path |
|
||||
| `PGSSLCRL` | Certificate revocation list path |
|
||||
| `PGREQUIREPEER` | Require peer username for Unix socket connections |
|
||||
| `PGKRBSRVNAME` | Kerberos service name |
|
||||
| `PGGSSLIB` | GSS library to use |
|
||||
| `PGCONNECT_TIMEOUT` | Connection timeout in seconds |
|
||||
| `PGCLIENTENCODING` | Client encoding (overrides auto-detected locale setting) |
|
||||
| `PGDATESTYLE` | Date display format |
|
||||
| `PGTZ` | Time zone |
|
||||
| `PGSYSCONFDIR` | System config directory |
|
||||
| `PG_COLOR` | Color output (`auto`, `always`, `never`) |
|
||||
| `COLUMNS` | When `\pset columns` is 0, controls `wrapped` format width and the threshold for activating pager or switching to expanded auto mode |
|
||||
| `PSQL_EDITOR` | Editor for `\e`, `\ef`, `\ev`. Takes precedence over `EDITOR` and `VISUAL`. |
|
||||
| `PSQL_EDITOR_LINENUMBER_ARG` | Command-line argument for passing line numbers to the editor (default: `+`). E.g., set to `--line ` for editors that use `--line N` syntax. |
|
||||
| `PSQL_HISTORY` | Alternative history file path (overrides `HISTFILE`) |
|
||||
| `PSQLRC` | Alternative `.psqlrc` location |
|
||||
| `PSQL_PAGER` | Pager command (overrides `PAGER`) |
|
||||
| `PSQL_WATCH_PAGER` | Pager command specifically for `\watch` output (overrides `PSQL_PAGER` and `PAGER` when set). Unix only. |
|
||||
| `EDITOR` / `VISUAL` | Editor for `\e`, `\ef`, `\ev` (checked after `PSQL_EDITOR`) |
|
||||
| `SHELL` | Shell for `\!` |
|
||||
| `TMPDIR` | Temp directory for temp files |
|
||||
| `LANG` | Locale (affects sorting, number formatting) |
|
||||
|
||||
### The ~/.pgpass File
|
||||
|
||||
Store passwords securely instead of using `PGPASSWORD`:
|
||||
|
||||
```
|
||||
# Format: hostname:port:database:username:password
|
||||
# Use * as wildcard
|
||||
localhost:5432:mydb:myuser:YOUR_PASSWORD
|
||||
*:5432:*:admin:YOUR_PASSWORD
|
||||
```
|
||||
|
||||
Permissions must be 0600: `chmod 600 ~/.pgpass`
|
||||
|
||||
---
|
||||
|
||||
## Configuration Files
|
||||
|
||||
### ~/.psqlrc
|
||||
|
||||
Executed on every interactive psql startup (unless `-X` is used). Perfect for personal customizations:
|
||||
|
||||
```sql
|
||||
-- ~/.psqlrc example
|
||||
\set ON_ERROR_STOP on
|
||||
\timing on
|
||||
\pset null '(null)'
|
||||
|
||||
-- Custom prompt showing database and transaction status
|
||||
\set PROMPT1 '%n@%m %/%x%# '
|
||||
|
||||
-- Shortcuts
|
||||
\set HISTSIZE 10000
|
||||
\set HISTCONTROL ignoredups
|
||||
|
||||
-- Show how long queries took
|
||||
\echo 'Welcome to' :DBNAME
|
||||
```
|
||||
|
||||
### Version-specific psqlrc
|
||||
|
||||
Append `-` and the version number for version-specific configuration. psql reads the most specific match:
|
||||
|
||||
- `~/.psqlrc-18` — applies for psql 18.x
|
||||
- `~/.psqlrc-18.3` — applies specifically for psql 18.3
|
||||
- System-level: `psqlrc-18` in the `pg_config --sysconfdir` directory
|
||||
|
||||
### System-wide psqlrc
|
||||
|
||||
System-level psql configuration at `pg_config --sysconfdir`/psqlrc (use `PGSYSCONFDIR` to override). Applied before user `~/.psqlrc`.
|
||||
|
||||
### Windows paths
|
||||
|
||||
On Windows, user config is at `%APPDATA%\postgresql\psqlrc.conf` and history at `%APPDATA%\postgresql\psql_history`.
|
||||
|
||||
---
|
||||
|
||||
## Tab Completion
|
||||
|
||||
psql provides intelligent tab completion for:
|
||||
- SQL keywords
|
||||
- Table, view, and column names
|
||||
- Function names and arguments
|
||||
- Schema-qualified names
|
||||
- `\d` command patterns
|
||||
|
||||
Tab completion sends queries to the server to fetch metadata. This can interfere with operations: e.g., after `BEGIN`, a tab completion query means `SET TRANSACTION ISOLATION LEVEL` is too late.
|
||||
|
||||
To disable tab completion permanently, add to `~/.inputrc`:
|
||||
```
|
||||
$if psql
|
||||
set disable-completion on
|
||||
$endif
|
||||
```
|
||||
|
||||
Or use `-n` to disable for a single session.
|
||||
|
||||
---
|
||||
|
||||
## Editor Integration
|
||||
|
||||
`\e`, `\ef`, and `\ev` use the editor specified by:
|
||||
1. `PSQL_EDITOR` environment variable (highest priority)
|
||||
2. `EDITOR` environment variable
|
||||
3. `VISUAL` environment variable
|
||||
4. Default: `vi` (Unix), `notepad.exe` (Windows)
|
||||
|
||||
Use `PSQL_EDITOR_LINENUMBER_ARG` to control how line numbers are passed (default: `+`).
|
||||
|
||||
**Useful editor settings:**
|
||||
```bash
|
||||
export EDITOR='vim'
|
||||
# or for VS Code:
|
||||
export EDITOR='code --wait'
|
||||
# or for nano:
|
||||
export EDITOR='nano'
|
||||
```
|
||||
@@ -0,0 +1,466 @@
|
||||
Part of the psql meta-command reference. See also: meta-commands-inspection.md, meta-commands-formatting.md
|
||||
|
||||
# psql Meta-Commands — Core Reference
|
||||
|
||||
Comprehensive reference for all psql backslash commands, organized by category. This covers every meta-command from the official PostgreSQL documentation.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [The Query Buffer](#the-query-buffer)
|
||||
- [Meta-Command Argument Parsing](#meta-command-argument-parsing)
|
||||
- [General](#general)
|
||||
- [Connection Management](#connection-management)
|
||||
- [Query Execution](#query-execution)
|
||||
- [Data Import/Export](#data-importexport)
|
||||
- [Large Objects](#large-objects)
|
||||
- [Scripting and Control Flow](#scripting-and-control-flow)
|
||||
- [Help and Information](#help-and-information)
|
||||
|
||||
---
|
||||
|
||||
## The Query Buffer
|
||||
|
||||
psql maintains an internal **query buffer** — a working area where SQL commands are assembled before being sent to the server. Understanding how the buffer works clarifies the behavior of many meta-commands:
|
||||
|
||||
- **Typing SQL** (without a terminating semicolon) appends text to the query buffer.
|
||||
- **Semicolon (`;`)** sends the buffer contents to the server and clears it.
|
||||
- **`\r` / `\reset`** discards the buffer without executing it.
|
||||
- **`\p` / `\print`** displays the current buffer contents.
|
||||
- **`\w` / `\write`** writes the buffer to a file or pipe.
|
||||
- **`\e` / `\edit`** opens the buffer in an external editor; when the editor closes, the modified content is re-parsed — complete queries (those ending with `;`) are executed immediately, and any remaining text stays in the buffer.
|
||||
- **`\g`** sends the buffer like a semicolon but accepts optional formatting and output-redirection arguments.
|
||||
- Many meta-commands that operate on "the query buffer" fall back to the most recently executed query if the buffer is empty (e.g., `\g`, `\gdesc`, `\p`).
|
||||
|
||||
---
|
||||
|
||||
## Meta-Command Argument Parsing
|
||||
|
||||
Most meta-commands accept arguments. Understanding how psql parses these arguments is essential for using them correctly, especially in scripts.
|
||||
|
||||
### Quoting Rules
|
||||
|
||||
Arguments are separated by whitespace. To include whitespace in an argument:
|
||||
|
||||
- **Single quotes**: `'hello world'` — the argument is `hello world`. Single quotes prevent variable interpolation and backquote expansion.
|
||||
- **Double quotes**: `"hello world"` — the argument is `hello world`. Variable interpolation (`:varname`) IS performed inside double quotes, but backquote expansion is NOT.
|
||||
- **Unquoted**: Arguments are delimited by whitespace; no quoting needed for single tokens.
|
||||
|
||||
### C-like Escape Sequences
|
||||
|
||||
Within single-quoted strings, these C-like escape sequences are recognized:
|
||||
|
||||
| Escape | Meaning |
|
||||
|--------|---------|
|
||||
| `\n` | Newline |
|
||||
| `\t` | Tab |
|
||||
| `\b` | Backspace |
|
||||
| `\r` | Carriage return |
|
||||
| `\f` | Form feed |
|
||||
| `\digits` | Octal byte value |
|
||||
| `\xhexdigits` | Hexadecimal byte value |
|
||||
|
||||
A backslash followed by any other character is treated as that character literally (e.g., `\\` → `\`, `\'` → `'`).
|
||||
|
||||
### Variable Interpolation in Arguments
|
||||
|
||||
psql variable references (`:varname`) are expanded in meta-command arguments wherever they appear, EXCEPT inside single-quoted strings. Double-quoted strings DO expand variable references.
|
||||
|
||||
```sql
|
||||
\set dest '/tmp/output.txt'
|
||||
\echo :dest -- expands to /tmp/output.txt
|
||||
\echo ':dest' -- literal :dest (no expansion)
|
||||
\echo ":dest" -- expands to /tmp/output.txt
|
||||
```
|
||||
|
||||
### Testing Variable Existence with `:{?varname}`
|
||||
|
||||
The syntax `:{?variable_name}` tests whether a variable is defined. It expands to `TRUE` or `FALSE` (literally), making it useful in `\if` conditions:
|
||||
|
||||
```sql
|
||||
\if :{?myvar}
|
||||
\echo 'myvar is defined'
|
||||
\else
|
||||
\echo 'myvar is not defined'
|
||||
\endif
|
||||
```
|
||||
|
||||
### Backquote Expansion
|
||||
|
||||
Text enclosed in backquotes (`` ` ``) within meta-command arguments is executed as a shell command, and its standard output (with trailing newlines removed) replaces the backquoted text. This is useful for injecting dynamic values:
|
||||
|
||||
```sql
|
||||
\echo `date` -- shows current date
|
||||
\echo `whoami` -- shows current OS user
|
||||
\set mydate `date +%Y%m%d`
|
||||
\echo :mydate -- e.g., 20260402
|
||||
```
|
||||
|
||||
Backquote expansion is NOT performed inside single-quoted strings or in lines that are skipped by `\if`/`\else`/`\elif`.
|
||||
|
||||
**Variable interpolation inside backquotes**: psql variable references (`:varname`, `:'varname'`) are expanded within backquoted text before the shell command is executed. This means you can use psql variables in shell commands:
|
||||
|
||||
```sql
|
||||
\set logfile /tmp/query.log
|
||||
\echo `cat :logfile` -- expands :logfile before running cat
|
||||
\echo `echo :'%varname'` -- :'...' form is preferred for shell safety
|
||||
```
|
||||
|
||||
The `:'varname'` form (quoted) is preferred inside backquotes because it properly escapes special characters. However, `:'varname'` will error if the variable value contains carriage return (`\r`) or line feed (`\n`) characters.
|
||||
|
||||
### SQL Identifier Arguments
|
||||
|
||||
Some meta-commands take arguments that describe database objects (e.g., `\df`, `\ef`). These follow special rules:
|
||||
|
||||
- Unquoted names are folded to lowercase (matching SQL identifier behavior)
|
||||
- Double-quoted names preserve case: `\df "MyFunction"`
|
||||
- Mixed quoting: unquoted parts are folded, double-quoted parts are preserved. `FOO"BAR"BAZ` becomes `fooBARbaz`
|
||||
- Trailing `()` with optional type names specifies argument types: `\df my_func(integer, text)`
|
||||
- `*` matches all: `\df *`
|
||||
|
||||
### Argument Parsing Stop Rules
|
||||
|
||||
- The entire remainder of the line is taken as the argument for commands like `\!`, `\copy`, `\o |command`, `\echo` (after processing quoting and interpolation).
|
||||
- A `\\` (double backslash) anywhere in the argument text causes psql to stop parsing at that point — everything before `\\` is the argument, everything after is ignored. This is useful for adding inline comments:
|
||||
```sql
|
||||
\echo hello \\ this is a comment
|
||||
-- outputs: hello
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## General
|
||||
|
||||
### `\;`
|
||||
|
||||
Appends a semicolon to the query buffer without triggering command execution. This allows combining multiple SQL statements into a single server request:
|
||||
|
||||
```sql
|
||||
select 1\; select 2\; select 3;
|
||||
```
|
||||
|
||||
All three statements are sent in one request when the non-backslashed semicolon is reached. The server executes them as a single transaction unless explicit `BEGIN`/`COMMIT` is included.
|
||||
|
||||
### `\! [command]`
|
||||
|
||||
With no argument, escapes to a sub-shell (psql resumes when sub-shell exits). With an argument, executes the shell command. The entire remainder of the line is taken as the command — no variable interpolation or backquote expansion.
|
||||
|
||||
```sql
|
||||
\! ls -la /tmp
|
||||
\! pwd
|
||||
```
|
||||
|
||||
### `\copyright`
|
||||
|
||||
Shows the copyright and distribution terms of PostgreSQL.
|
||||
|
||||
---
|
||||
|
||||
## Connection Management
|
||||
|
||||
### `\c` or `\connect [ -reuse-previous=on|off ] [ dbname [ username ] [ host ] [ port ] | conninfo ]`
|
||||
|
||||
Establishes a new connection to a PostgreSQL server. If the connection succeeds, the previous connection is closed.
|
||||
|
||||
**Positional syntax:**
|
||||
```sql
|
||||
\c mydb myuser host.dom 6432
|
||||
\c - - newhost - -- change only the host
|
||||
```
|
||||
|
||||
**Connection string syntax:**
|
||||
```sql
|
||||
\c service=foo
|
||||
\c "host=localhost port=5432 dbname=mydb connect_timeout=10 sslmode=disable"
|
||||
\c postgresql://tom@localhost/mydb?application_name=myapp
|
||||
```
|
||||
|
||||
**`-reuse-previous` flag:**
|
||||
- By default, parameters are re-used in positional syntax, but NOT with conninfo strings
|
||||
- Pass `-reuse-previous=on` to re-use all unspecified parameters from the current connection
|
||||
- Pass `-reuse-previous=off` to prevent re-use
|
||||
|
||||
```sql
|
||||
\c -reuse-previous=on sslmode=require -- changes only sslmode
|
||||
```
|
||||
|
||||
**Behavior on failure:**
|
||||
- Interactive mode: previous connection is kept
|
||||
- Script mode: previous connection is closed; all database commands fail until next successful `\c`
|
||||
|
||||
### `\conninfo`
|
||||
|
||||
Outputs connection information including database, user, host, port, and SSL status. The `Client User` field shows the user at connection time; `Superuser` shows whether the current execution context has superuser privileges (may differ after `SET ROLE`).
|
||||
|
||||
### `\encoding [ encoding ]`
|
||||
|
||||
Sets the client character set encoding. Without an argument, shows the current encoding.
|
||||
|
||||
### `\password [ username ]`
|
||||
|
||||
Changes the password for the specified user (default: current user). Prompts for the new password, encrypts it, and sends it as `ALTER ROLE`. The new password does NOT appear in command history, server log, or anywhere else.
|
||||
|
||||
---
|
||||
|
||||
## Query Execution
|
||||
|
||||
### `\g [ (option=value [...]) ] [ filename ]` / `\g [ (option=value [...]) ] [ |command ]`
|
||||
|
||||
Sends the current query buffer to the server for execution.
|
||||
|
||||
- Without arguments: equivalent to a semicolon
|
||||
- With a filename: output written to file (only if the query succeeds and returns zero or more tuples)
|
||||
- With `|command`: output piped to shell command (no variable interpolation in command). Only written if the query succeeds and returns zero or more tuples.
|
||||
|
||||
**Note**: The file or command is written to only if the query successfully returns zero or more tuples — not if the query fails or is a non-data-returning SQL command. This means even an empty result set (0 rows) will trigger output.
|
||||
|
||||
```sql
|
||||
SELECT * FROM users \g (format=csv footer=off) /tmp/users.csv
|
||||
SELECT count(*) FROM users \g | wc -l
|
||||
```
|
||||
|
||||
If the query buffer is empty, the most recently sent query is re-executed.
|
||||
|
||||
### `\gx [ (option=value [...]) ] [ filename ]`
|
||||
|
||||
Like `\g`, but forces expanded output mode for this query (as if `expanded=on` were included).
|
||||
|
||||
### `\gdesc`
|
||||
|
||||
Shows the column names and data types of the result without actually executing the query. Syntax errors are still reported. If the query buffer is empty, describes the most recently sent query.
|
||||
|
||||
### `\gset [ prefix ]`
|
||||
|
||||
Executes the query and stores the result in psql variables. The query must return exactly one row. Each column becomes a variable named after the column (optionally prefixed). NULL columns unset the variable rather than setting it. If the query fails or does not return one row, no variables are changed.
|
||||
|
||||
```sql
|
||||
SELECT 'hello' AS var1, 10 AS var2
|
||||
\gset result_
|
||||
\echo :result_var1 :result_var2
|
||||
-- outputs: hello 10
|
||||
```
|
||||
|
||||
### `\gexec`
|
||||
|
||||
Executes the current query, then treats each column of each row as a SQL statement to execute. NULL fields are ignored. Generated queries are sent literally — no psql meta-commands or variable references. Execution continues on error unless `ON_ERROR_STOP` is set. Setting `ECHO` to `all` or `queries` is recommended when using `\gexec` to see what's being executed.
|
||||
|
||||
```sql
|
||||
SELECT format('CREATE INDEX ON my_table(%I)', attname)
|
||||
FROM pg_attribute
|
||||
WHERE attrelid = 'my_table'::regclass AND attnum > 0
|
||||
ORDER BY attnum
|
||||
\gexec
|
||||
```
|
||||
|
||||
### `\crosstabview [ colV [ colH [ colD [ sortcolH ] ] ] ]`
|
||||
|
||||
Executes the query and displays results as a crosstab (pivot table). The query must return at least three columns. Column specs can be column numbers (1-based) or names.
|
||||
|
||||
- `colV` — vertical header (default: column 1)
|
||||
- `colH` — horizontal header (default: column 2, must differ from colV)
|
||||
- `colD` — data displayed in the grid (default: the remaining column)
|
||||
- `sortcolH` — optional sort column for horizontal header (must be integers)
|
||||
|
||||
Error is reported if multiple rows map to the same cell.
|
||||
|
||||
### `\bind [ parameter ] ...`
|
||||
|
||||
Sets query parameters for the next query execution. Uses the extended query protocol. Can be combined with `\g`, `\gx`, or `\gset`:
|
||||
|
||||
```sql
|
||||
INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g
|
||||
SELECT * FROM tbl1 WHERE id = $1 \bind 'first value' \gx
|
||||
SELECT id, name FROM tbl1 WHERE id = $1 \bind 'first value' \gset result_
|
||||
```
|
||||
|
||||
### `\bind_named statement_name [ parameter ] ...`
|
||||
|
||||
Like `\bind`, but takes the name of an existing prepared statement as the first parameter.
|
||||
|
||||
```sql
|
||||
INSERT INTO tbls1 VALUES ($1, $2) \parse stmt1
|
||||
\bind_named stmt1 'first value' 'second value' \g
|
||||
```
|
||||
|
||||
### `\parse statement_name`
|
||||
|
||||
Creates a prepared statement from the current query buffer. An empty string denotes the unnamed prepared statement.
|
||||
|
||||
```sql
|
||||
SELECT $1 \parse stmt1
|
||||
```
|
||||
|
||||
### `\close_prepared statement_name`
|
||||
|
||||
Closes the specified prepared statement. No-op if it doesn't exist.
|
||||
|
||||
```sql
|
||||
SELECT $1 \parse stmt1
|
||||
\close_prepared stmt1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Data Import/Export
|
||||
|
||||
### `\copy`
|
||||
|
||||
Performs a client-side copy. Unlike SQL `COPY`, this runs with the client's filesystem and permissions (no superuser required).
|
||||
|
||||
```
|
||||
\copy { table [(column_list)] } FROM { 'filename' | program 'command' | stdin | pstdin }
|
||||
[ [ WITH ] ( option [, ...] ) ] [ WHERE condition ]
|
||||
|
||||
\copy { table [(column_list)] | (query) } TO { 'filename' | program 'command' | stdout | pstdout }
|
||||
[ [ WITH ] ( option [, ...] ) ]
|
||||
```
|
||||
|
||||
**Key behaviors:**
|
||||
- The entire remainder of the line is always taken as arguments (no variable interpolation or backquote expansion)
|
||||
- For `FROM stdin`, data continues until `\.` or EOF
|
||||
- `pstdin`/`pstdout` always use psql's actual stdin/stdout regardless of `\o` setting
|
||||
- All options other than source/destination are as specified for SQL `COPY`
|
||||
|
||||
**WARNING**: `program 'command'` executes a shell command with client user privileges. Never concatenate untrusted input.
|
||||
|
||||
**Tip**: For multi-line copy or variable interpolation, use `COPY ... TO STDOUT` terminated with `\g filename` or `\g |command`.
|
||||
|
||||
---
|
||||
|
||||
## Large Objects
|
||||
|
||||
### `\lo_export loid filename`
|
||||
|
||||
Reads the large object with the given OID from the database and writes it to the specified file. Uses client-side permissions (unlike server-side `lo_export`).
|
||||
|
||||
### `\lo_import filename [ comment ]`
|
||||
|
||||
Imports a file as a large object. Returns the OID assigned. Always provide a human-readable comment.
|
||||
|
||||
```sql
|
||||
\lo_import '/home/user/photo.jpg' 'product photo'
|
||||
-- Returns: lo_import 152801
|
||||
```
|
||||
|
||||
### `\lo_list[x+]`
|
||||
|
||||
Lists all large objects in the database with their comments. `+` shows permissions.
|
||||
|
||||
### `\lo_unlink loid`
|
||||
|
||||
Deletes the large object with the specified OID.
|
||||
|
||||
---
|
||||
|
||||
## Scripting and Control Flow
|
||||
|
||||
### `\i` / `\include` filename
|
||||
|
||||
Reads and executes input from the file. Relative to current working directory. Use `-` for stdin.
|
||||
|
||||
**stdin behavior**: When using `\i -`, psql reads from standard input until an EOF indication or `\q` meta-command. This can be used to intersperse interactive input with input from files. Note that Readline editing is only available at the outermost level — it is not active when reading from a nested file.
|
||||
|
||||
### `\ir` / `\include_relative` filename
|
||||
|
||||
Like `\i`, but resolves relative paths from the directory of the currently executing script (not the working directory). Prefer `\ir` for portable scripts.
|
||||
|
||||
### `\o` / `\out [ filename ]` / `\o [ |command ]`
|
||||
|
||||
Redirects query output to file or pipe. `\o` without arguments resets to stdout. When argument starts with `|`, the rest is passed literally to the shell (no variable interpolation).
|
||||
|
||||
**What gets redirected**: "Query results" includes tables, command responses, notices, and output from `\d` commands — but **not error messages**. Error messages always go to stderr.
|
||||
|
||||
**What doesn't get redirected**: `\echo` outputs to stdout (not affected by `\o`); use `\qecho` for redirected output.
|
||||
|
||||
**Tip**: To intersperse text between query results in a redirected output file, use `\qecho`.
|
||||
|
||||
### `\echo text [ ... ]`
|
||||
|
||||
Prints arguments to stdout, separated by spaces, followed by a newline. If first argument is unquoted `-n`, no trailing newline is written.
|
||||
|
||||
### `\qecho text [ ... ]`
|
||||
|
||||
Like `\echo` but outputs to the query output channel (set by `\o`).
|
||||
|
||||
### `\warn text [ ... ]`
|
||||
|
||||
Like `\echo` but outputs to stderr.
|
||||
|
||||
### `\set [ name [ value [ ... ] ] ]`
|
||||
|
||||
Sets a psql variable. Multiple values are concatenated. `\set` without arguments shows all variables. Variable names are case-sensitive, can contain letters, digits, underscores.
|
||||
|
||||
This is unrelated to the SQL `SET` command.
|
||||
|
||||
### `\unset name`
|
||||
|
||||
Unsets (deletes) a psql variable. Most control variables cannot be truly unset; they revert to defaults.
|
||||
|
||||
### `\prompt [ text ] name`
|
||||
|
||||
Prompts the user for input and stores it in the named variable. For multiword prompts, surround with single quotes.
|
||||
|
||||
**Behavior with `-f` flag**: When psql is invoked with `-f` (reading commands from a file), `\prompt` reads from stdin/stdout rather than the terminal. In interactive mode, it uses the terminal directly.
|
||||
|
||||
### `\getenv psql_var env_var`
|
||||
|
||||
Reads an environment variable and stores it in a psql variable. No change if the env var is undefined.
|
||||
|
||||
```sql
|
||||
\getenv home HOME
|
||||
\echo :home
|
||||
-- outputs: /home/postgres
|
||||
```
|
||||
|
||||
### `\setenv name [ value ]`
|
||||
|
||||
Sets or unsets an environment variable from within psql.
|
||||
|
||||
```sql
|
||||
\setenv PAGER less
|
||||
\setenv LESS -imx4F
|
||||
```
|
||||
|
||||
### `\p` / `\print`
|
||||
|
||||
Prints the current query buffer to stdout. If the buffer is empty, prints the most recently executed query.
|
||||
|
||||
### `\w` / `\write` filename / `\w |command`
|
||||
|
||||
Writes the current query buffer to a file or pipes it to a shell command. If the buffer is empty, writes the most recently executed query. When argument starts with `|`, rest is passed literally to the shell.
|
||||
|
||||
### `\if` / `\elif` / `\else` / `\endif`
|
||||
|
||||
Nestable conditional blocks. `\if` and `\elif` evaluate their argument as a boolean (true/false/1/0/on/off/yes/no, case-insensitive). All backslash commands in a conditional block must appear in the same source file.
|
||||
|
||||
```sql
|
||||
SELECT EXISTS(SELECT 1 FROM customer WHERE customer_id = 123) as is_customer,
|
||||
EXISTS(SELECT 1 FROM employee WHERE employee_id = 456) as is_employee
|
||||
\gset
|
||||
\if :is_customer
|
||||
SELECT * FROM customer WHERE customer_id = 123;
|
||||
\elif :is_employee
|
||||
\echo 'is not a customer but is an employee'
|
||||
SELECT * FROM employee WHERE employee_id = 456;
|
||||
\else
|
||||
\echo 'not a customer or employee'
|
||||
\endif
|
||||
```
|
||||
|
||||
Variable references in skipped lines are NOT expanded. Backquote expansion is NOT performed in skipped lines.
|
||||
|
||||
---
|
||||
|
||||
## Help and Information
|
||||
|
||||
### `\? [ topic ]`
|
||||
|
||||
Shows psql help. Topics:
|
||||
- `commands` (default) — backslash commands
|
||||
- `options` — command-line options
|
||||
- `variables` — configuration variables
|
||||
|
||||
### `\h` / `\help [ command ]`
|
||||
|
||||
SQL syntax help. Without arguments, lists available commands. `*` shows help for all commands. Multi-word commands don't need quoting: `\h ALTER TABLE`.
|
||||
|
||||
Unlike most meta-commands, the entire line is the argument — no variable interpolation.
|
||||
+154
@@ -0,0 +1,154 @@
|
||||
Part of the psql meta-command reference. See also: meta-commands-core.md, meta-commands-inspection.md
|
||||
|
||||
# psql Meta-Commands — Output Formatting & Pipeline Mode
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Output Formatting](#output-formatting)
|
||||
- [Pipeline Mode](#pipeline-mode)
|
||||
- [Session Management](#session-management)
|
||||
|
||||
---
|
||||
|
||||
## Output Formatting
|
||||
|
||||
### `\pset [ option [ value ] ]`
|
||||
|
||||
Sets options affecting query result table output. Without arguments, displays current settings.
|
||||
|
||||
| Option | Values | Description |
|
||||
|--------|--------|-------------|
|
||||
| `border` | 0-2 (3 for latex) | Border/line style. Higher = more lines. |
|
||||
| `columns` | integer | Target width for wrapped format. 0 = use `COLUMNS` env or screen width. Non-zero also wraps output when sent to file or pipe (normally file/pipe output is unwrapped). |
|
||||
| `csv_fieldsep` | character | CSV field separator (default: comma) |
|
||||
| `expanded` (or `x`) | `on`, `off`, `auto` | Vertical display. `auto` uses expanded when wider than screen. Note: `auto` is only effective in `aligned` and `wrapped` formats. |
|
||||
| `fieldsep` | string | Field separator for unaligned output (default: `\|`) |
|
||||
| `fieldsep_zero` | — | Set field separator to NUL byte |
|
||||
| `footer` | `on`, `off` | Toggle row count footer display |
|
||||
| `format` | `aligned`, `asciidoc`, `csv`, `html`, `latex`, `latex-longtable`, `troff-ms`, `unaligned`, `wrapped` | Output format. See format descriptions below. |
|
||||
| `linestyle` | `ascii`, `old-ascii`, `unicode` | Border character style. `ascii` uses `+`, `-`, `|` characters. `old-ascii` uses `:` and `;` for borders. `unicode` uses Unicode box-drawing characters. |
|
||||
| `null` | string | Display string for NULL values (default: empty) |
|
||||
| `numericlocale` | `on`, `off` | Locale-specific number formatting |
|
||||
| `pager` | `on`, `off`, `always` | Pager control. Uses `PSQL_PAGER` or `PAGER` env. For `\watch` output, `PSQL_WATCH_PAGER` takes precedence over both. |
|
||||
| `pager_min_lines` | integer | Minimum lines before pager activates (default: 0) |
|
||||
| `recordsep` | string | Record separator for unaligned mode (default: newline) |
|
||||
| `recordsep_zero` | — | Set record separator to NUL byte |
|
||||
| `tableattr` (or `T`) | string | HTML: table tag attributes (e.g., `border=1`). latex-longtable: whitespace-separated proportional column widths (e.g., `'0.2 0.2 0.6'`). |
|
||||
| `title` (or `C`) | string | Table title. Unset with no value. |
|
||||
| `tuples_only` (or `t`) | `on`, `off` | Show only data, no headers/footers |
|
||||
| `unicode_border_linestyle` | `single`, `double` | Unicode border drawing |
|
||||
| `unicode_column_linestyle` | `single`, `double` | Unicode column drawing |
|
||||
| `unicode_header_linestyle` | `single`, `double` | Unicode header drawing |
|
||||
| `xheader_width` | `full`, `column`, `page`, or integer | Max width of expanded output header |
|
||||
|
||||
### Format Descriptions
|
||||
|
||||
| Format | Description |
|
||||
|--------|-------------|
|
||||
| `aligned` | Standard human-readable table with column alignment (default). |
|
||||
| `wrapped` | Like `aligned` but long values wrap to fit column width. Headers with underscores are not repeated on continuation rows. |
|
||||
| `unaligned` | All columns on one line, separated by `fieldsep`. Useful for script output. |
|
||||
| `csv` | RFC 4180 compliant CSV output. Uses `csv_fieldsep` (default: comma). Safe for import into spreadsheets and other tools. |
|
||||
| `html` | HTML `<table>` markup. |
|
||||
| `asciidoc` | AsciiDoc table format for documentation. |
|
||||
| `latex` | LaTeX tabular format. |
|
||||
| `latex-longtable` | LaTeX longtable format for multi-page tables. Supports proportional column widths via `\pset tableattr` (e.g., `'0.2 0.2 0.6'`). |
|
||||
| `troff-ms` | troff ms macros table format. |
|
||||
|
||||
### Formatting shortcuts
|
||||
|
||||
| Shortcut | Equivalent |
|
||||
|----------|-----------|
|
||||
| `\a` | `\pset format unaligned` (toggle) |
|
||||
| `\C [title]` | `\pset title` |
|
||||
| `\f [string]` | `\pset fieldsep` |
|
||||
| `\H` | `\pset format html` (toggle) |
|
||||
| `\t` | `\pset tuples_only` (toggle) |
|
||||
| `\T table_options` | `\pset tableattr` |
|
||||
| `\x [on\|off\|auto]` | `\pset expanded` |
|
||||
|
||||
---
|
||||
|
||||
## Pipeline Mode
|
||||
|
||||
Pipeline mode batches SQL statements into fewer network round trips for better performance. Available in PostgreSQL 14+.
|
||||
|
||||
### Pipeline commands
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `\startpipeline` | Begin a pipeline block |
|
||||
| `\endpipeline` | End a pipeline block and process remaining results |
|
||||
| `\sendpipeline` | Append current query buffer to pipeline without waiting for results |
|
||||
| `\syncpipeline` | Send a sync message without ending the pipeline |
|
||||
| `\flushrequest` | Request server flush without sync |
|
||||
| `\flush` | Manually push unsent data to server |
|
||||
| `\getresults [N]` | Read pending results (N=0 or omitted = all) |
|
||||
|
||||
### Pipeline rules
|
||||
|
||||
- All queries in pipeline mode use the extended query protocol
|
||||
- Queries are appended with semicolons or `\sendpipeline`
|
||||
- Allowed meta-commands: `\bind`, `\bind_named`, `\parse`, `\close_prepared`
|
||||
- NOT allowed: `\g`, `\gx`, `\gdesc` (and other result-consuming commands)
|
||||
- `COPY` is not supported in pipeline mode
|
||||
- A `%P` prompt variable is available to show pipeline status (`on`, `off`, or `abort`)
|
||||
|
||||
### Example
|
||||
|
||||
```sql
|
||||
\startpipeline
|
||||
SELECT * FROM pg_class;
|
||||
SELECT 1 \bind \sendpipeline
|
||||
\flushrequest
|
||||
\getresults
|
||||
\endpipeline
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Session Management
|
||||
|
||||
### `\e` / `\edit [ filename ] [ line_number ]`
|
||||
|
||||
Opens the query buffer (or a file) in the external editor. On save, the buffer is re-parsed. Complete queries are immediately executed. The cursor is positioned on the specified line number. See `$EDITOR` / `$VISUAL` for editor configuration.
|
||||
|
||||
### `\ef [ function_description [ line_number ] ]`
|
||||
|
||||
Edits a function or procedure definition as a `CREATE OR REPLACE FUNCTION/PROCEDURE` command. Specify function by name or name and argument types. Without arguments, shows a blank template. Line number positions within the function body.
|
||||
|
||||
Unlike most meta-commands, the entire line is the argument — no variable interpolation.
|
||||
|
||||
### `\ev [ view_name [ line_number ] ]`
|
||||
|
||||
Edits a view definition as a `CREATE OR REPLACE VIEW` command. Without arguments, shows a blank template.
|
||||
|
||||
### `\cd [ directory ]`
|
||||
|
||||
Changes the current working directory. Without an argument, changes to the home directory.
|
||||
|
||||
```sql
|
||||
\cd /tmp
|
||||
\! pwd -- /tmp
|
||||
\cd -- back to home directory
|
||||
```
|
||||
|
||||
### `\r` / `\reset`
|
||||
|
||||
Clears the query buffer.
|
||||
|
||||
### `\s [ filename ]`
|
||||
|
||||
Prints command history to file or stdout. Requires Readline support.
|
||||
|
||||
### `\timing [ on | off ]`
|
||||
|
||||
Toggles (or explicitly sets) display of query execution time. Shown in milliseconds; intervals > 1s also show minutes:seconds, hours, days as needed.
|
||||
|
||||
### `\errverbose`
|
||||
|
||||
Repeats the most recent server error message at maximum verbosity (as if `VERBOSITY=verbose` and `SHOW_CONTEXT=always`).
|
||||
|
||||
### `\restrict restrict_key` / `\unrestrict restrict_key`
|
||||
|
||||
Enter/exit restricted mode where only `\unrestrict` is allowed. Key must be alphanumeric. Primarily used by `pg_dump`/`pg_restore`.
|
||||
+134
@@ -0,0 +1,134 @@
|
||||
Part of the psql meta-command reference. See also: meta-commands-core.md, meta-commands-formatting.md
|
||||
|
||||
# psql Meta-Commands — Object Inspection (\d family)
|
||||
|
||||
This document covers all `\d` family commands for inspecting database objects, including tables, indexes, functions, schemas, and more.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Object Inspection (\d family)](#object-inspection-d-family)
|
||||
- [Pattern matching rules](#pattern-matching-rules)
|
||||
|
||||
---
|
||||
|
||||
## Object Inspection (\d family)
|
||||
|
||||
All `\d` commands accept these common modifiers:
|
||||
- `+` — extra info (size, description, ownership)
|
||||
- `S` — include system objects
|
||||
- `x` — expanded display (must follow `S` or `+`, NOT immediately after `\d`)
|
||||
|
||||
**Important**: The `x` modifier for expanded display must appear after `S` or `+` (e.g., `\dt+x`), because `\dx` is a separate command that lists installed extensions. Writing `\dx` when you meant expanded display will show extensions instead.
|
||||
|
||||
All accept a pattern parameter with wildcard matching (`*`, `?`, regex). See Patterns section below.
|
||||
|
||||
### `\d[Sx+] [ pattern ]`
|
||||
|
||||
Without a pattern: equivalent to `\dtvmsE` (lists all visible tables, views, materialized views, sequences, and foreign tables).
|
||||
|
||||
With a pattern: shows columns, types, tablespace, special attributes (NOT NULL, defaults), indexes, constraints, rules, triggers. For foreign tables, shows the foreign server.
|
||||
|
||||
`\d+` adds: column comments, OID presence, view definition, replica identity, access method.
|
||||
|
||||
### Table-type listing commands
|
||||
|
||||
`\dE` / `\di` / `\dm` / `\ds` / `\dt` / `\dv` — List foreign tables, indexes, materialized views, sequences, tables, or views. Combine letters: `\dti` lists both tables and indexes.
|
||||
|
||||
`\d+` adds: persistence status (permanent/temporary/unlogged), physical size on disk, description.
|
||||
|
||||
### Aggregate and function listings
|
||||
|
||||
| Command | Shows |
|
||||
|---------|-------|
|
||||
| `\da[Sx] [pattern]` | Aggregate functions with return type and input types |
|
||||
| `\df[anptwSx+] [pattern [arg_pattern ...]]` | Functions. Filter by type: `a`=agg, `n`=normal, `p`=procedure, `t`=trigger, `w`=window. Additional args match parameter type names. Use `-` as last arg_pattern to prevent matching functions with extra args. Example: `\df * integer` lists functions whose first argument is `integer`. |
|
||||
| `\do[Sx+] [pattern [arg_pattern [arg_pattern]]]` | Operators with operand/result types. One arg matches prefix operators; two args match binary operators. Use `-` for unused operand. Example: `\do + integer integer` lists `+` operators with two integer args. |
|
||||
|
||||
### Schema and type listings
|
||||
|
||||
| Command | Shows |
|
||||
|---------|-------|
|
||||
| `\dn[Sx+] [pattern]` | Schemas (namespaces) |
|
||||
| `\dT[Sx+] [pattern]` | Data types (`\dT+` shows internal name, size, enum values, permissions) |
|
||||
| `\dC[x+] [pattern]` | Type casts (`\dC+` shows leakproof status and description) |
|
||||
| `\dD[Sx+] [pattern]` | Domains (`\dD+` shows permissions and description) |
|
||||
| `\dO[Sx+] [pattern]` | Collations (only collations usable with current database encoding — results vary by database) |
|
||||
|
||||
### Access method and operator listings
|
||||
|
||||
| Command | Shows |
|
||||
|---------|-------|
|
||||
| `\dA[x+] [pattern]` | Access methods |
|
||||
| `\dAc[x+] [am_pattern [type_pattern]]` | Operator classes |
|
||||
| `\dAf[x+] [am_pattern [type_pattern]]` | Operator families |
|
||||
| `\dAo[x+] [am_pattern [family_pattern]]` | Operators in families |
|
||||
| `\dAp[x+] [am_pattern [family_pattern]]` | Support functions in families |
|
||||
|
||||
### Configuration and privilege listings
|
||||
|
||||
| Command | Shows |
|
||||
|---------|-------|
|
||||
| `\dconfig[x+] [pattern]` | Server config parameters. Without a pattern, shows only non-default values. `\dconfig+` adds data type, context, and access privileges. |
|
||||
| `\dp[Sx] [pattern]` | Table/view/sequence privileges |
|
||||
| `\ddp[x] [pattern]` | Default access privileges |
|
||||
| `\drg[Sx] [pattern]` | Granted role memberships (ADMIN, INHERIT, SET options, grantor) |
|
||||
| `\drds[x] [role_pattern [db_pattern]]` | Per-role and per-database config settings |
|
||||
| `\z[Sx] [pattern]` | Alias for `\dp` |
|
||||
|
||||
### Replication and partition listings
|
||||
|
||||
| Command | Shows |
|
||||
|---------|-------|
|
||||
| `\dP[itnx+] [pattern]` | Partitioned relations (`t`=tables, `i`=indexes, `n`=nested shows parent) |
|
||||
| `\dRp[x+] [pattern]` | Replication publications (`\dRp+` shows associated tables/schemas) |
|
||||
| `\dRs[x+] [pattern]` | Replication subscriptions (`\dRs+` shows additional properties) |
|
||||
|
||||
### Extended statistics, extensions, and more
|
||||
|
||||
| Command | Shows |
|
||||
|---------|-------|
|
||||
| `\dX[x] [pattern]` | Extended statistics. Status column shows `defined` (requested) or NULL (not requested) per statistic kind. Use `pg_stats_ext` to check if `ANALYZE` has been run. |
|
||||
| `\dx[x+] [pattern]` | Installed extensions (`\dx+` lists all objects in each extension) |
|
||||
| `\dy[x+] [pattern]` | Event triggers |
|
||||
| `\dd[Sx] [pattern]` | Object descriptions (comments on constraints, operator classes, operator families, rules, triggers). Other object comments are shown by their respective `\d` commands. |
|
||||
|
||||
### Foreign data wrapper listings
|
||||
|
||||
| Command | Shows |
|
||||
|---------|-------|
|
||||
| `\des[x+] [pattern]` | Foreign servers |
|
||||
| `\det[x+] [pattern]` | Foreign tables (`\det+` shows options and description) |
|
||||
| `\deu[x+] [pattern]` | User mappings (CAUTION: `\deu+` may show passwords) |
|
||||
| `\dew[x+] [pattern]` | Foreign-data wrappers |
|
||||
|
||||
### Text search listings
|
||||
|
||||
| Command | Shows |
|
||||
|---------|-------|
|
||||
| `\dF[x+] [pattern]` | Text search configurations (`\dF+` shows parser and dictionary list per token type) |
|
||||
| `\dFd[x+] [pattern]` | Text search dictionaries |
|
||||
| `\dFp[x+] [pattern]` | Text search parsers (`\dFp+` shows functions and recognized token types) |
|
||||
| `\dFt[x+] [pattern]` | Text search templates |
|
||||
|
||||
### Other object listings
|
||||
|
||||
| Command | Shows |
|
||||
|---------|-------|
|
||||
| `\db[x+] [pattern]` | Tablespaces (`\db+` shows options, size, permissions, description) |
|
||||
| `\dc[Sx+] [pattern]` | Character-set encoding conversions |
|
||||
| `\dl[x+]` | Large objects (alias for `\lo_list`) |
|
||||
| `\dL[Sx+] [pattern]` | Procedural languages |
|
||||
| `\du[Sx+] [pattern]` / `\dg[Sx+] [pattern]` | Database roles (`\du` = `\dg`, since users and groups were unified into roles) |
|
||||
| `\l[x+] [pattern]` | Databases (`\l+` shows size, default tablespace, description. Size only available for databases you can connect to.) |
|
||||
| `\sf[+] func_desc` | Function definition (read-only, `+` numbers lines from body start) |
|
||||
| `\sv[+] view_name` | View definition (read-only, `+` numbers lines) |
|
||||
|
||||
### Pattern matching rules
|
||||
|
||||
All `\d` commands that accept a pattern use the same matching system:
|
||||
|
||||
1. **Case folding**: Unquoted letters are folded to lowercase (like SQL identifiers). Double quotes prevent folding.
|
||||
2. **Wildcards**: `*` matches any character sequence, `?` matches any single character. Within double quotes, these are literal.
|
||||
3. **Dot separator**: A dot (`.`) separates schema from object name. Two dots separate database.schema.object (database must match current connection).
|
||||
4. **Regex**: Advanced patterns like `[0-9]` work. `.` is a separator (not regex any-char), `*` → `.*`, `?` → `.`, `$` is literal. Within double quotes, all regex specials are literal.
|
||||
5. **No pattern**: Shows all objects visible in the current schema search path (equivalent to `*`). Use `*.*` to see all objects regardless of visibility.
|
||||
@@ -0,0 +1,289 @@
|
||||
# psql Tips — Advanced Debugging, Performance & Safety
|
||||
|
||||
Part of the psql tips reference. See also: tips-workflows.md
|
||||
|
||||
Advanced techniques for debugging, performance tuning, and safe psql usage.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Performance Tips](#performance-tips)
|
||||
- [Debugging and Introspection](#debugging-and-introspection)
|
||||
- [Safety and Best Practices](#safety-and-best-practices)
|
||||
- [Gotchas and Common Mistakes](#gotchas-and-common-mistakes)
|
||||
|
||||
---
|
||||
|
||||
## Performance Tips
|
||||
|
||||
### Large Result Sets
|
||||
|
||||
```sql
|
||||
-- Don't load entire result into memory
|
||||
\set FETCH_COUNT 1000
|
||||
SELECT * FROM billion_row_table;
|
||||
|
||||
-- Use \copy instead of COPY for client-side operations
|
||||
\copy huge_table TO '/data/export.csv' WITH (FORMAT csv)
|
||||
```
|
||||
|
||||
### Pipeline Mode for Batch Operations
|
||||
|
||||
Pipeline mode batches multiple queries into single network round trips:
|
||||
|
||||
```sql
|
||||
\startpipeline
|
||||
INSERT INTO logs (msg) VALUES ($1)
|
||||
\bind 'entry 1' \sendpipeline
|
||||
INSERT INTO logs (msg) VALUES ($1)
|
||||
\bind 'entry 2' \sendpipeline
|
||||
INSERT INTO logs (msg) VALUES ($1)
|
||||
\bind 'entry 3' \sendpipeline
|
||||
\getresults
|
||||
\endpipeline
|
||||
```
|
||||
|
||||
This sends all three INSERTs in one network round trip instead of three.
|
||||
|
||||
### Script Execution
|
||||
|
||||
```bash
|
||||
# Run in a single transaction (faster, and all-or-nothing)
|
||||
psql -1 -f migration.sql mydb
|
||||
|
||||
# Multiple files sequentially
|
||||
psql -1 -f 001.sql -f 002.sql -f 003.sql mydb
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Debugging and Introspection
|
||||
|
||||
### See What psql Sends to the Server
|
||||
|
||||
```sql
|
||||
-- Echo all SQL commands
|
||||
\set ECHO queries
|
||||
|
||||
-- See the SQL behind \d commands (incredibly useful for learning)
|
||||
\set ECHO_HIDDEN on
|
||||
|
||||
-- Or in noexec mode (show but don't execute)
|
||||
\set ECHO_HIDDEN noexec
|
||||
|
||||
-- Now run any \d command to see its SQL
|
||||
\dt
|
||||
\d users
|
||||
```
|
||||
|
||||
### Check Query Plans
|
||||
|
||||
```sql
|
||||
-- Basic plan
|
||||
EXPLAIN SELECT * FROM users WHERE email = 'test@example.com';
|
||||
|
||||
-- With actual execution time
|
||||
EXPLAIN ANALYZE SELECT * FROM users WHERE email = 'test@example.com';
|
||||
|
||||
-- Detailed with buffer info
|
||||
EXPLAIN (ANALYZE, BUFFERS, VERBOSE) SELECT ...;
|
||||
|
||||
-- JSON format for tooling
|
||||
EXPLAIN (FORMAT JSON) SELECT ...;
|
||||
```
|
||||
|
||||
### Lock Analysis
|
||||
|
||||
```sql
|
||||
-- Current locks waiting to be granted
|
||||
SELECT * FROM pg_locks WHERE NOT granted;
|
||||
|
||||
-- Blocked sessions with their blockers (PostgreSQL 9.6+)
|
||||
SELECT blocked.pid,
|
||||
blocked.query,
|
||||
pg_blocking_pids(blocked.pid) AS blocked_by_pids
|
||||
FROM pg_stat_activity blocked
|
||||
WHERE cardinality(pg_blocking_pids(blocked.pid)) > 0;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Safety and Best Practices
|
||||
|
||||
### Always Set ON_ERROR_STOP in Scripts
|
||||
|
||||
Without `ON_ERROR_STOP`, a script continues even after errors, potentially leaving the database in an inconsistent state:
|
||||
|
||||
```sql
|
||||
-- Top of every script
|
||||
\set ON_ERROR_STOP on
|
||||
```
|
||||
|
||||
### Use Single-Transaction Mode for Migrations
|
||||
|
||||
```bash
|
||||
# -1 wraps everything in BEGIN...COMMIT
|
||||
# On error, the entire migration rolls back
|
||||
psql -1 -f migration.sql mydb
|
||||
```
|
||||
|
||||
### Never Use PGPASSWORD in Scripts
|
||||
|
||||
```bash
|
||||
# BAD: Password visible in process list, env vars
|
||||
PGPASSWORD=secret psql -c "SELECT 1" mydb# GOOD: Use ~/.pgpass (manually edit to avoid shell history)
|
||||
touch ~/.pgpass && chmod 600 ~/.pgpass
|
||||
# Then edit ~/.pgpass and your add:
|
||||
# hostname:port:database:username:password
|
||||
# Example: localhost:5432:mydb:myuser:mysecret
|
||||
psql -c "SELECT 1" mydb
|
||||
```
|
||||
|
||||
### Preview Before Executing
|
||||
|
||||
```sql
|
||||
-- Dry-run a script to see what commands will execute (shows SQL, does NOT execute)
|
||||
\set ECHO all
|
||||
BEGIN;
|
||||
-- Paste or review migration SQL here, then ROLLBACK instead of COMMIT
|
||||
\i migration.sql
|
||||
ROLLBACK;
|
||||
|
||||
-- Or use \gdesc to check result columns without executing
|
||||
SELECT * FROM complex_view \gdesc
|
||||
```
|
||||
|
||||
### Use \copy Over COPY
|
||||
|
||||
`\copy` uses client permissions and filesystem. SQL `COPY` runs on the server and requires superuser or `pg_read_server_files`/`pg_write_server_files` roles. `\copy` transfers all data through the client/server connection, which is less efficient than SQL `COPY` for very large datasets. For bulk data transfer, prefer SQL `COPY` when server-side file access is available.
|
||||
|
||||
```sql
|
||||
-- BAD (requires server-side file access)
|
||||
COPY users TO '/tmp/users.csv' WITH CSV HEADER;
|
||||
|
||||
-- GOOD (uses client-side file access)
|
||||
\copy users TO '/tmp/users.csv' WITH CSV HEADER
|
||||
```
|
||||
|
||||
### search_path Safety for Untrusted Users
|
||||
|
||||
If untrusted users have access to the database, remove publicly-writable schemas from `search_path` at session start:
|
||||
|
||||
```sql
|
||||
SELECT pg_catalog.set_config('search_path', '', false);
|
||||
```
|
||||
|
||||
### Automatic LISTEN/NOTIFY Polling
|
||||
|
||||
Whenever a command is executed, psql automatically polls for asynchronous notification events generated by `LISTEN`/`NOTIFY`. This happens without any special configuration.
|
||||
|
||||
---
|
||||
|
||||
## Gotchas and Common Mistakes
|
||||
|
||||
### Semicolons in \copy
|
||||
|
||||
`\copy` does NOT end with a semicolon. It's a meta-command:
|
||||
|
||||
```sql
|
||||
-- CORRECT
|
||||
\copy users TO '/tmp/users.csv' WITH CSV HEADER
|
||||
|
||||
-- WRONG (psql interprets the semicolon oddly)
|
||||
\copy users TO '/tmp/users.csv' WITH CSV HEADER;
|
||||
```
|
||||
|
||||
### Variable Substitution and SQL Injection
|
||||
|
||||
psql variables are simple text substitution. They are NOT parameterized queries:
|
||||
|
||||
```sql
|
||||
-- The :'varname' form (single-quoted) escapes embedded single quotes, making it
|
||||
-- safe against SQL injection for STRING VALUES in WHERE clauses:
|
||||
\set name "Robert'); DROP TABLE students;--"
|
||||
SELECT * FROM users WHERE name = :'name';
|
||||
-- Expands to: WHERE name = 'Robert''); DROP TABLE students;--'
|
||||
-- The '' is an escaped quote, so the entire value is a single string literal — NOT injected.
|
||||
|
||||
-- However, :'varname' is NOT safe for identifiers or unquoted contexts.
|
||||
-- For identifiers (table/column names), use :"varname" (double-quoted form).
|
||||
-- For the safest parameterized queries, use \bind:
|
||||
SELECT * FROM users WHERE name = $1;
|
||||
\bind 'Robert' \g
|
||||
```
|
||||
|
||||
### Transaction State After Error
|
||||
|
||||
After an error in a transaction block, all subsequent commands fail until ROLLBACK:
|
||||
|
||||
```sql
|
||||
BEGIN;
|
||||
INSERT INTO users (id) VALUES (1);
|
||||
INSERT INTO users (id) VALUES ('bad'); -- ERROR
|
||||
INSERT INTO users (id) VALUES (2); -- Also fails!
|
||||
COMMIT; -- Also fails!
|
||||
```
|
||||
|
||||
Use `ON_ERROR_ROLLBACK` to auto-savepoint:
|
||||
|
||||
```sql
|
||||
\set ON_ERROR_ROLLBACK on
|
||||
BEGIN;
|
||||
INSERT INTO users (id) VALUES (1);
|
||||
INSERT INTO users (id) VALUES ('bad'); -- ERROR, auto-rollback to savepoint
|
||||
INSERT INTO users (id) VALUES (2); -- This works now
|
||||
COMMIT;
|
||||
```
|
||||
|
||||
### Pattern Matching Uses Regex
|
||||
|
||||
The `*` and `?` in \d commands are converted to regex (`.*` and `.`). Advanced regex like `[0-9]` works. Important differences from standard regex:
|
||||
|
||||
- `.` is a schema/object separator, not any-char (use `?` for any single char)
|
||||
- `$` is matched literally, not as an anchor (pattern must match whole name anyway)
|
||||
- Within double quotes, all special characters (`*`, `?`, regex chars) are literal
|
||||
|
||||
```sql
|
||||
-- These work as expected
|
||||
\dt user* -- matches users, user_accounts, etc.
|
||||
\dt user? -- matches users, user1, etc.
|
||||
\dt user[0-9]* -- matches user1, user2, user123
|
||||
|
||||
-- If your table name contains special chars, use double quotes
|
||||
\dt "table.with.dots" -- matches literally, dots not treated as separator
|
||||
```
|
||||
|
||||
### Connection String vs CLI Arguments
|
||||
|
||||
```bash
|
||||
# These are equivalent
|
||||
psql -h localhost -p 5432 -U admin -d mydb
|
||||
psql "postgresql://admin@localhost:5432/mydb"
|
||||
|
||||
# But you can't mix freely — URI overrides individual flags
|
||||
psql -h otherhost "postgresql://admin@localhost:5432/mydb" -- uses localhost, not otherhost
|
||||
```
|
||||
|
||||
### \i vs \ir
|
||||
|
||||
- `\i filename` — resolves relative to the **current working directory** (where psql was started)
|
||||
- `\ir filename` — resolves relative to the **currently executing script's directory**
|
||||
|
||||
For script portability, prefer `\ir`:
|
||||
|
||||
```sql
|
||||
-- In /scripts/migrations/run_all.sql:
|
||||
\ir 001_schema.sql -- resolves to /scripts/migrations/001_schema.sql
|
||||
\ir 002_data.sql -- resolves to /scripts/migrations/002_data.sql
|
||||
```
|
||||
|
||||
### \o and Query Output
|
||||
|
||||
`\o` redirects query output, not meta-command output:
|
||||
|
||||
```sql
|
||||
\o /tmp/output.txt
|
||||
SELECT * FROM users; -- goes to file
|
||||
\d users -- also goes to file
|
||||
\echo 'hello' -- goes to STDOUT (not affected by \o)
|
||||
\qecho 'hello' -- goes to /tmp/output.txt (affected by \o)
|
||||
```
|
||||
@@ -0,0 +1,407 @@
|
||||
# psql Tips — Workflows & Patterns
|
||||
|
||||
Part of the psql tips reference. See also: tips-advanced.md
|
||||
|
||||
Practical workflows and common patterns for getting the most out of psql.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Pattern Matching in \d Commands](#pattern-matching-in-d-commands)
|
||||
- [Common Workflows](#common-workflows)
|
||||
- [Scripting Patterns](#scripting-patterns)
|
||||
- [Output for Scripts and Automation](#output-for-scripts-and-automation)
|
||||
- [Data Import/Export Patterns](#data-importexport-patterns)
|
||||
|
||||
---
|
||||
|
||||
## Pattern Matching in \d Commands
|
||||
|
||||
All `\d` commands that accept a pattern parameter use the same matching rules. Understanding these rules is key to efficient database exploration.
|
||||
|
||||
### Pattern Syntax
|
||||
|
||||
| Pattern | Meaning | Example |
|
||||
| ------- | ------- | ------- |
|
||||
| `*` | Any sequence of characters | `\dt user*` matches `users`, `user_accounts` |
|
||||
| `?` | Any single character | `\dt user?` matches `users` but not `user_accounts` |
|
||||
| `.` | Separates schema from object | `\dt public.*` lists all tables in `public` |
|
||||
|
||||
### How Matching Works
|
||||
|
||||
1. **Dot notation**: If the pattern contains a dot, the part before the dot matches schema names, the part after matches object names. `\dt public.users` means schema=`public`, table=`users`.
|
||||
|
||||
2. **No dot**: Matches objects in schemas on the current `search_path`. `\dt users` finds `users` in any searchable schema.
|
||||
|
||||
3. **Wildcard expansion**: `*` and `?` are expanded into regular expressions:
|
||||
- `*` becomes `.*` (any characters)
|
||||
- `?` becomes `.` (one character)
|
||||
- Advanced regex notations like `[0-9]` work for character classes
|
||||
- `.` in pattern position is a schema/object separator (not regex any-char)
|
||||
- `$` is matched literally (not regex anchor)
|
||||
|
||||
4. **Case folding**: Unquoted letters in patterns are folded to lowercase (matching SQL identifier behavior). `\dt FOO` finds table `foo`. Double quotes prevent folding: `\dt "FOO"` finds table `FOO` (not `foo`).
|
||||
|
||||
### Practical Examples
|
||||
|
||||
```sql
|
||||
-- All tables in any schema containing "user"
|
||||
\dt *.user*
|
||||
|
||||
-- All tables in the public schema
|
||||
\dt public.*
|
||||
|
||||
-- All tables starting with "order" in any schema
|
||||
\dt *.order*
|
||||
|
||||
-- Detail view of a specific table
|
||||
\d+ public.users
|
||||
|
||||
-- All indexes on tables starting with "user"
|
||||
\di user*
|
||||
|
||||
-- All functions in the public schema
|
||||
\df public.*
|
||||
|
||||
-- All materialized views
|
||||
\dm
|
||||
|
||||
-- Check table size and description
|
||||
\dt+ public.*
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Common Workflows
|
||||
|
||||
### Exploring a New Database
|
||||
|
||||
```sql
|
||||
-- Step 1: What databases exist?
|
||||
\l
|
||||
|
||||
-- Step 2: Connect to one
|
||||
\c mydb
|
||||
|
||||
-- Step 3: What schemas are there?
|
||||
\dn
|
||||
|
||||
-- Step 4: What tables exist?
|
||||
\dt
|
||||
|
||||
-- Step 5: What does this table look like?
|
||||
\d users
|
||||
|
||||
-- Step 6: Any indexes?
|
||||
\di
|
||||
|
||||
-- Step 7: Any views?
|
||||
\dv
|
||||
|
||||
-- Step 8: What functions exist?
|
||||
\df
|
||||
|
||||
-- Step 9: What extensions are installed?
|
||||
\dx
|
||||
|
||||
-- Step 10: Check current settings
|
||||
SHOW all;
|
||||
```
|
||||
|
||||
### Understanding Table Structure
|
||||
|
||||
```sql
|
||||
-- Basic structure: columns, types, nullable, defaults
|
||||
\d table_name
|
||||
|
||||
-- Detailed: everything above plus indexes, constraints, triggers, storage info
|
||||
\d+ table_name
|
||||
|
||||
-- Just the indexes
|
||||
\di table_name*
|
||||
|
||||
-- Just the foreign keys (shown in \d output)
|
||||
\d table_name
|
||||
-- Look for "Foreign-key constraints" section
|
||||
|
||||
-- Column comments
|
||||
\dS+ table_name -- includes system columns
|
||||
|
||||
-- Storage details (toast, compression)
|
||||
\d+ table_name
|
||||
```
|
||||
|
||||
### Checking Query Performance
|
||||
|
||||
```sql
|
||||
-- Enable timing
|
||||
\timing on
|
||||
|
||||
-- See the execution plan
|
||||
EXPLAIN ANALYZE SELECT * FROM users WHERE email = 'test@example.com';
|
||||
|
||||
-- See what the optimizer actually does
|
||||
EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT) SELECT ...;
|
||||
|
||||
-- Check current activity
|
||||
SELECT * FROM pg_stat_activity WHERE state = 'active';
|
||||
|
||||
-- Watch a query
|
||||
SELECT pg_size_pretty(pg_database_size(current_database()));
|
||||
\watch 60
|
||||
```
|
||||
|
||||
### Managing Transactions Manually
|
||||
|
||||
```sql
|
||||
\set AUTOCOMMIT off
|
||||
|
||||
BEGIN;
|
||||
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
|
||||
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
|
||||
COMMIT;
|
||||
|
||||
\set AUTOCOMMIT on
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Scripting Patterns
|
||||
|
||||
### Safe Script Template
|
||||
|
||||
```sql
|
||||
-- Always start with this in scripts
|
||||
\set ON_ERROR_STOP on
|
||||
\set VERBOSITY verbose
|
||||
|
||||
-- Optional: echo commands for debugging
|
||||
\set ECHO all
|
||||
|
||||
-- Your migration or operations go here
|
||||
BEGIN;
|
||||
|
||||
ALTER TABLE users ADD COLUMN IF NOT EXISTS phone varchar(20);
|
||||
|
||||
COMMIT;
|
||||
```
|
||||
|
||||
### Conditional Execution
|
||||
|
||||
```sql
|
||||
-- \if evaluates its argument as a boolean (true/false/1/0/on/off/yes/no)
|
||||
-- For string comparison, use SQL to set a boolean variable:
|
||||
SELECT current_setting('is_production', true) = 'true' AS is_prod \gset
|
||||
\if :is_prod
|
||||
\echo 'WARNING: Running on PRODUCTION'
|
||||
-- \if only accepts boolean values. To check user input for a specific string,
|
||||
-- use SQL to produce a boolean result:
|
||||
\prompt 'Type YES to continue: ' confirm
|
||||
SELECT :'confirm' = 'YES' AS confirmed \gset
|
||||
\if :confirmed
|
||||
\echo 'Continuing...'
|
||||
\else
|
||||
\echo 'Aborted.'
|
||||
\endif
|
||||
\endif
|
||||
|
||||
-- Check if a variable is defined using :{?varname}
|
||||
\if :{?required_var}
|
||||
\echo 'required_var is set to:' :required_var
|
||||
\else
|
||||
\echo 'ERROR: required_var is not defined. Aborting.'
|
||||
\q
|
||||
\endif
|
||||
```
|
||||
|
||||
### Dynamic SQL with \gexec
|
||||
|
||||
```sql
|
||||
-- Generate and execute ANALYZE for all tables
|
||||
SELECT 'ANALYZE ' || schemaname || '.' || tablename
|
||||
FROM pg_tables
|
||||
WHERE schemaname NOT IN ('pg_catalog', 'information_schema');
|
||||
\gexec
|
||||
|
||||
-- Generate GRANT statements
|
||||
SELECT 'GRANT SELECT ON ' || tablename || ' TO readonly;'
|
||||
FROM pg_tables
|
||||
WHERE schemaname = 'public';
|
||||
\gexec
|
||||
|
||||
-- Create partition tables dynamically
|
||||
SELECT 'CREATE TABLE measurements_' || to_char(d, 'YYYY_MM') ||
|
||||
' PARTITION OF measurements FOR VALUES FROM (''' ||
|
||||
to_char(d, 'YYYY-MM-01') || ''') TO (''' ||
|
||||
to_char(d + interval '1 month', 'YYYY-MM-01') || ''');'
|
||||
FROM generate_series('2024-01-01'::date, '2024-12-01'::date, '1 month') AS d;
|
||||
\gexec
|
||||
```
|
||||
|
||||
### Backquote Expansion (Shell Command Substitution)
|
||||
|
||||
Text inside backquotes (`` ` ``) in meta-command arguments is executed as a shell command, and the output replaces the backquoted text. This lets you inject dynamic values from the OS into psql:
|
||||
|
||||
```sql
|
||||
-- Inject current date into a variable
|
||||
\set report_date `date +%Y-%m-%d`
|
||||
\echo :report_date
|
||||
-- outputs: 2026-04-02
|
||||
|
||||
-- Use shell output in a file path
|
||||
\o /tmp/query_output_`date +%Y%m%d_%H%M%S`.csv
|
||||
SELECT * FROM users;
|
||||
\o
|
||||
|
||||
-- Show system information
|
||||
\echo 'Running as user: ' `whoami`
|
||||
\echo 'Hostname: ' `hostname`
|
||||
|
||||
-- Use shell arithmetic
|
||||
\set batch_size `echo 1000`
|
||||
SELECT * FROM users LIMIT :batch_size;
|
||||
|
||||
-- Combine with \setenv for dynamic configuration
|
||||
\setenv PAGER `which less`
|
||||
```
|
||||
|
||||
**Limitations**:
|
||||
|
||||
- Backquote expansion is NOT performed inside single-quoted strings
|
||||
- Not performed in lines skipped by `\if`/`\else`/`\elif`
|
||||
- Not performed in `\copy` arguments (the entire line is taken literally)
|
||||
|
||||
**Variable expansion inside backquotes**: psql variable references (`:varname`, `:'varname'`) ARE expanded within backquoted text before the shell command is executed. The `:'varname'` form is preferred because it properly escapes special characters for shell safety. However, `:'varname'` will error if the variable value contains carriage return or line feed characters.
|
||||
|
||||
```sql
|
||||
-- Get table count and use it
|
||||
SELECT count(*) as user_count FROM users;
|
||||
\gset
|
||||
\echo 'Total users: ' :user_count
|
||||
|
||||
-- Get max ID and use in next query
|
||||
SELECT max(id) as max_id FROM orders;
|
||||
\gset
|
||||
SELECT * FROM orders WHERE id > :max_id - 10;
|
||||
|
||||
-- Prefix to avoid collisions
|
||||
SELECT oid, relname FROM pg_class WHERE relname = 'users';
|
||||
\gset pg_
|
||||
\echo 'OID of users table: ' :pg_oid
|
||||
```
|
||||
|
||||
### Include Other Scripts
|
||||
|
||||
```sql
|
||||
-- Relative to current working directory
|
||||
\i init/001_schema.sql
|
||||
\i init/002_seed.sql
|
||||
\i init/003_permissions.sql
|
||||
|
||||
-- Relative to this file's location (better for portability)
|
||||
\ir ../shared/helpers.sql
|
||||
```
|
||||
|
||||
### Loop Pattern (using shell)
|
||||
|
||||
```bash
|
||||
# Not a psql feature, but a common pattern combining shell and psql
|
||||
for table in users orders products; do
|
||||
psql -c "SELECT count(*) FROM $table" mydb
|
||||
done
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Output for Scripts and Automation
|
||||
|
||||
### Machine-Readable Output
|
||||
|
||||
```bash
|
||||
# CSV output
|
||||
psql -A -F ',' -t -c "SELECT id, name FROM users" mydb
|
||||
|
||||
# TSV output
|
||||
psql -A -F $'\t' -t -c "SELECT id, name FROM users" mydb
|
||||
|
||||
# Single value (no header, no border)
|
||||
psql -A -t -c "SELECT count(*) FROM users" mydb
|
||||
|
||||
# JSON output (use PostgreSQL's JSON functions)
|
||||
psql -A -t -c "SELECT json_agg(t) FROM (SELECT id, name FROM users) t" mydb
|
||||
|
||||
# NUL-separated (for xargs -0)
|
||||
# WARNING: Ensure filenames from the database are trusted before piping to destructive commands
|
||||
psql -A -0 -t -c "SELECT filename FROM files_to_process" mydb | xargs -0 process_file
|
||||
```
|
||||
|
||||
### In-Session Output Control
|
||||
|
||||
```sql
|
||||
-- Quick CSV dump
|
||||
\pset format csv
|
||||
\o /tmp/output.csv
|
||||
SELECT id, name, email FROM users;
|
||||
\o
|
||||
\pset format aligned
|
||||
|
||||
-- Using \g options (no need to change global settings)
|
||||
SELECT * FROM users \g (format=csv footer=off) /tmp/users.csv
|
||||
|
||||
-- Pipe to a command
|
||||
SELECT pg_database_size(current_database()) \g | numfmt --to=iec
|
||||
|
||||
-- Unaligned for quick copy-paste
|
||||
\a
|
||||
\t on
|
||||
SELECT string_agg(column_name, ', ') FROM information_schema.columns WHERE table_name = 'users';
|
||||
\t off
|
||||
\a
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Data Import/Export Patterns
|
||||
|
||||
### CSV Import
|
||||
|
||||
```sql
|
||||
-- Standard CSV import
|
||||
\copy table_name FROM 'data.csv' WITH (FORMAT csv, HEADER true)
|
||||
|
||||
-- Custom delimiter
|
||||
\copy table_name FROM 'data.tsv' WITH (FORMAT csv, HEADER true, DELIMITER E'\t')
|
||||
|
||||
-- Handle NULLs
|
||||
\copy table_name FROM 'data.csv' WITH (FORMAT csv, HEADER true, NULL 'N/A')
|
||||
|
||||
-- Specific columns only
|
||||
\copy table_name (col1, col2, col3) FROM 'partial.csv' WITH (FORMAT csv, HEADER true)
|
||||
```
|
||||
|
||||
### CSV Export
|
||||
|
||||
```sql
|
||||
-- Full table export
|
||||
\copy table_name TO 'export.csv' WITH (FORMAT csv, HEADER true)
|
||||
|
||||
-- Query export
|
||||
\copy (SELECT id, name, created_at FROM users WHERE active ORDER BY created_at DESC) TO 'active_users.csv' WITH (FORMAT csv, HEADER true)
|
||||
|
||||
-- Compressed export (pipe through gzip, no intermediate file)
|
||||
\copy table_name TO program 'gzip > export.csv.gz' WITH (FORMAT csv, HEADER true)-- Import from compressed (decompress on the fly)
|
||||
\copy table_name FROM program 'gzip -dc import.csv.gz' WITH (FORMAT csv, HEADER true)
|
||||
```
|
||||
|
||||
### Database Migration Between Servers
|
||||
|
||||
```bash
|
||||
# Dump and restore via pipe (no intermediate file)
|
||||
pg_dump -Fc source_db | pg_restore -d target_db
|
||||
|
||||
# Schema-only dump
|
||||
pg_dump --schema-only source_db | psql target_db
|
||||
|
||||
# Data-only with parallel jobs
|
||||
pg_dump -j4 -Fd source_db -f /tmp/dump_dir
|
||||
pg_restore -j4 -d target_db /tmp/dump_dir
|
||||
```
|
||||
Reference in New Issue
Block a user