Search 110+ PostgreSQL commands and snippets — psql CLI, data types, DDL, DML, indexes, JOINs, CTEs, window functions, JSONB, and roles. Click any card to copy.
Showing 141 of 141 entries — click any card to copy
Frequently Asked Questions
What is the difference between JSON and JSONB in PostgreSQL?
JSON stores data as plain text exactly as it was input — it preserves whitespace, key order, and duplicate keys. JSONB stores data in a parsed binary format, which discards whitespace, normalises key order, and removes duplicate keys. JSONB is faster to query because it does not need to re-parse the text on each access, and it supports GIN indexes that enable fast containment checks (@>) and key existence queries. For almost all use cases, JSONB is the better choice. Use JSON only if you need to preserve the exact original text representation.
How do I do an upsert (INSERT OR UPDATE) in PostgreSQL?
PostgreSQL supports upserts via the ON CONFLICT clause on INSERT statements. Use ON CONFLICT (column) DO UPDATE SET col = EXCLUDED.col to update the conflicting row with the new values — EXCLUDED refers to the row that was proposed for insertion. Use ON CONFLICT (column) DO NOTHING to silently ignore the insert if a conflict occurs. The conflict target must be a unique constraint or primary key. This is available since PostgreSQL 9.5.
What is the difference between SERIAL and GENERATED ALWAYS AS IDENTITY?
SERIAL is a legacy shorthand that creates a sequence and sets a column default to nextval(). It has a quirk: the column default can be overridden or the sequence can be accessed directly, making it less predictable. GENERATED ALWAYS AS IDENTITY (available since PostgreSQL 10) is the SQL-standard approach. It creates a true identity column where PostgreSQL manages the sequence and prevents manual inserts unless you specify OVERRIDING SYSTEM VALUE. GENERATED BY DEFAULT AS IDENTITY allows manual inserts. For new projects, prefer the identity column syntax.
How do window functions differ from GROUP BY?
GROUP BY collapses multiple rows into a single row per group and you can only select the grouping columns or aggregate functions. Window functions (using the OVER clause) compute a value across a set of related rows but return a value for every row — the original rows are preserved. This lets you do things like rank each row within a group, compute a running total, access the previous or next row's value, or find the first value in a group, all while still seeing every individual row in the result.
How do I check for slow queries in PostgreSQL?
First, enable the pg_stat_statements extension (CREATE EXTENSION pg_stat_statements) to collect query statistics. Query SELECT query, calls, total_exec_time, mean_exec_time FROM pg_stat_statements ORDER BY mean_exec_time DESC LIMIT 20 to find the slowest average queries. For currently running queries, check SELECT pid, query, now() - query_start AS duration FROM pg_stat_activity WHERE state = 'active' ORDER BY duration DESC. Use EXPLAIN ANALYZE on suspect queries to see the actual execution plan and identify sequential scans on large tables that would benefit from an index.