psql ist der mit PostgreSQL ausgelieferte Kommandozeilen-Client — und in der Praxis das wichtigste Werkzeug, um eine Postgres-Datenbank im Detail zu erkunden. Im Vergleich zu GUI-Tools ist psql schnell, überall verfügbar und versteht viele Aufgaben über kurze Meta-Commands. Dieser Artikel deckt das Wichtigste ab: Verbindung, Schema-Erkundung, Output-Formatierung, kleine Komfort-Tricks und ein sinnvolles ~/.psqlrc.

Verbindung herstellen

psql versteht eine Reihe von Connection-Flags. Die wichtigsten:

FlagWirkungDefault
-h <host>Hostname / SocketLokaler Unix-Socket
-p <port>Port5432
-U <user>Postgres-RolleAktueller Shell-User
-d <db>Ziel-DatenbankGleicher Name wie -U
-WPasswort interaktiv erzwingenaus pg_hba.conf abgeleitet

Typische Aufrufe:

Bash Verschiedene Verbindungs-Varianten
# Lokal als aktueller User in die Datenbank "myapp"
psql myapp

# Expliziter User und Datenbank ueber TCP
psql -h localhost -U app -d myapp

# Remote-Server
psql -h db.example.com -U app -d myapp

Alternativ als Connection-URI in einem einzigen Argument:

Bash
psql "postgresql://app:secret@localhost:5432/myapp"

Praktisch fürs Kopieren aus Tools wie Doppler, .env oder dem Cloud-Dashboard.

Passwort sicher hinterlegen: in ~/.pgpass mit Format host:port:db:user:password, Permissions chmod 600. psql liest die Datei automatisch und braucht dann kein -W.

Eingabe-Modi und Beenden

Im interaktiven Modus zeigt psql einen Prompt mit Datenbankname:

Bash
myapp=#

Das # signalisiert, dass du als Superuser verbunden bist; ein normaler User sieht =>. Mehrzeilige Statements werden bis zum abschließenden ; gesammelt; der Prompt wechselt zu myapp-# bzw. myapp-(>, solange ein Statement offen ist.

Beenden des Clients:

Bash
\q

Oder schlicht mit Ctrl+D.

Meta-Commands — die Backslash-Welt

Alles, was mit Backslash beginnt, ist ein psql-eigener Befehl, kein SQL. Die wichtigsten Familien:

Hilfe und Übersicht

CommandWirkung
\?Hilfe zu allen Meta-Commands
\hHilfe zu SQL-Statements (z. B. \h CREATE TABLE)
\lListe aller Datenbanken im Cluster
\duListe aller Rollen mit Attributen (\du+ zeigt zusätzliche Spalten)
\dnListe aller Schemas

Schema-Erkundung

CommandWirkung
\dAlle Relationen (Tabellen, Views, Sequenzen) im aktuellen Schema
\d <name>Detail-Beschreibung einer Relation: Spalten, Indexe, FKs, Trigger
\dtNur Tabellen
\dvNur Views
\dmNur Materialized Views
\dfFunktionen
\df+ <name>Funktion inkl. Quelltext
\diIndexe
\dsSequenzen
\dxInstallierte Extensions
\dp <name>Privilegien auf Relation

Ein einzelnes + am Ende vieler Commands (\d+, \df+, \dt+) zeigt zusätzliche Spalten — Größe, Beschreibung, Storage-Optionen.

Datenbank wechseln

SQL
\c andere_db
\c andere_db andere_user

\c baut eine neue Connection auf — die alte wird geschlossen. Nützlich, wenn man im selben psql-Prozess zwischen mehreren Datenbanken springen will.

Output-Formatierung

Bei Tabellen mit vielen Spalten oder breiten Werten wird die Default-Tabellen-Ansicht schnell unleserlich. psql hat dafür Schalter:

CommandWirkung
\xErweiterte Anzeige (eine Spalte pro Zeile) — toggle
\x autoAutomatisch erweitert, wenn die Zeile nicht passt
\pset format aligned|unaligned|csv|jsonOutput-Format
\pset null '∅'Anzeige von NULL-Werten
\pset linestyle unicodeHübschere Tabellenränder
\pset border 2Mehr Tabellenränder

Beispiel: \x auto mit Output in Markdown-tauglichem Stil:

SQL Erweiterte Anzeige fuer eine breite Zeile
myapp=# \x auto
myapp=# SELECT * FROM users WHERE id = 1;
-[ RECORD 1 ]----+----------------------
id               | 1
email            | alice@example.com
created_at       | 2026-04-01 10:23:14+00
last_login_at    | 2026-05-05 18:02:11+00

Kleine Komfort-Tricks

\timing — Query-Dauer messen

SQL
myapp=# \timing
Timing is on.
myapp=# SELECT count(*) FROM events;
 count
--------
 184223
Time: 24.117 ms

Sehr nützlich, um schnell ein Gefühl für Query-Performance zu bekommen. Für seriöses Profiling bleibt EXPLAIN ANALYZE das Mittel der Wahl.

\e — Statement im Editor öffnen

Öffnet den letzten Query-Buffer in $EDITOR. Beim Speichern und Schließen wird das Statement ausgeführt. Praktisch für längere SQL-Stücke, ohne dass man eine separate Datei anlegt.

\watch <sek> — Query wiederholen

SQL
myapp=# SELECT count(*) FROM jobs WHERE status='pending';
myapp=# \watch 5

Führt die letzte Query alle 5 Sekunden erneut aus — ein simples Live-Dashboard auf der CLI.

\copy — schnelle Datenübernahme

Im Gegensatz zu COPY (das auf dem Server läuft und Server-Pfade braucht) liest \copy lokal:

SQL
myapp=# \copy users FROM 'users.csv' WITH (FORMAT csv, HEADER true);
myapp=# \copy (SELECT * FROM users) TO 'export.csv' WITH (FORMAT csv, HEADER true);

\gexec — Output als nächstes SQL ausführen

Zwei-Schritt-Pattern: erst eine Query, die Statements erzeugt, dann \gexec führt jeden zurückgegebenen Wert als eigenes Statement aus:

SQL Alle alten Tabellen droppen
SELECT format('DROP TABLE IF EXISTS %I CASCADE;', tablename)
FROM pg_tables
WHERE schemaname = 'public' AND tablename LIKE 'tmp_%' \gexec

~/.psqlrc — psql persönlicher machen

psql lädt beim Start ~/.psqlrc. Damit kannst du sinnvolle Defaults setzen:

Bash ~/.psqlrc
\set QUIET 1
\pset null '∅'
\pset linestyle unicode
\pset border 2
\x auto
\timing
\set HISTFILE ~/.psql_history- :DBNAME
\set HISTSIZE 5000
\set PROMPT1 '%[%033[1;32m%]%n@%/%[%033[0m%]%R%# '
\set PROMPT2 '%[%033[1;32m%]%/%[%033[0m%]%R%# '
\unset QUIET

Was passiert hier: NULL wird sichtbar (), Tabellen kriegen Unicode-Ränder, \x auto schaltet bei breiten Zeilen automatisch auf erweiterte Ansicht, \timing ist immer an, der Prompt zeigt User und DB, und die History wird pro Datenbank getrennt — sehr praktisch, wenn du regelmäßig auf mehreren DBs arbeitest.

Besonderheiten

\d ist die schnellste Schema-Doku, die es gibt.

Es zeigt Spalten mit Typen, NOT-NULL und Defaults, alle Indexe (inkl. UNIQUE und Partial), Foreign Keys ein- und ausgehend, Trigger, Check-Constraints und Inheritance. Schneller als jedes ER-Diagramm — und immer aktuell, weil direkt aus dem Katalog.

\h liefert die SQL-Syntax direkt aus der Doku.

\h CREATE TABLE zeigt die komplette BNF-Syntax aus der offiziellen PostgreSQL-Doku, inkl. Link am Ende. Wenn du nur kurz nachsehen willst, ob eine Klausel RETURNING heißt oder OUTPUT, ist das schneller als ein Browser-Tab.

\copy läuft auf dem Client, COPY auf dem Server.

COPY users FROM '/path/to/file' erwartet die Datei am Server-Filesystem und braucht Superuser-Rechte. \copy liest und schreibt mit den Rechten des psql-Aufrufers — meistens das, was du wirklich willst. Aufpassen: in Skripten immer \copy, nicht COPY.

\g und \gexec sind Killer-Features für SQL-Generierung.

\g führt das aktuelle Statement nochmal mit anderen Parametern aus, \gexec führt das Ergebnis als SQL aus. Damit kannst du Refactorings („alle Tabellen mit Suffix _old droppen”), Bulk-Statements aus dem Katalog oder Code-Generation komplett in psql machen — ohne externe Skript-Sprache.

\watch macht psql zum Mini-Live-Dashboard.

Für eine schnelle Auge-darauf-Halten-Schicht — Queue-Tiefe, langsame Sessions, Replikations-Lag — reicht oft <Query> + \watch 2. Kein Grafana, kein Datadog, kein Tab-Switch. Beendet wird es mit Ctrl+C.

Variablen in psql: \set, :variable, :'variable', :"variable".

psql kennt eigene Variablen, die nichts mit SQL-Variablen zu tun haben. \set tbl users definiert eine; :tbl ersetzt sie roh, :'tbl' als String-Literal, :"tbl" als Identifier. Praktisch für wiederverwendbare Skripte: SELECT count(*) FROM :"tbl";.

Weiterführende Ressourcen

Externe Quellen

/ Weiter

Zurück zu Grundlagen

Zur Übersicht