PostgreSQL Cheatsheet
A User-friendly guide to PostgreSQL database operations. Learn SQL queries, data types, indexing, and performance optimization.
Basic Operations
Database Management
Basic database operations.
-- Connect to PostgreSQL
psql -U username -d database
-- List all databases
\l or \list
-- Create database
CREATE DATABASE dbname;
-- Switch database
\c dbname
-- Drop database
DROP DATABASE dbname;
-- Show current database
SELECT current_database();
-- Show all tables
\dt
-- Describe table
\d tablename
Table Operations
Creating and managing tables.
-- Create table
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
age INTEGER CHECK (age >= 18),
is_active BOOLEAN DEFAULT true
);
-- Modify table
ALTER TABLE users ADD COLUMN phone VARCHAR(15);
ALTER TABLE users DROP COLUMN phone;
ALTER TABLE users ALTER COLUMN email TYPE VARCHAR(150);
ALTER TABLE users RENAME TO accounts;
-- Drop table
DROP TABLE users;
-- Truncate table
TRUNCATE TABLE users;
TRUNCATE TABLE users CASCADE; -- With related tables
CRUD Operations
Insert Data
Adding records to tables.
-- Insert single row
INSERT INTO users (username, email, age)
VALUES ('alex', 'alex@example.com', 25);
-- Insert multiple rows
INSERT INTO users (username, email, age) VALUES
('emma', 'emma@example.com', 28),
('michael', 'michael@example.com', 32);
-- Insert with returning
INSERT INTO users (username, email)
VALUES ('sarah', 'sarah@example.com')
RETURNING id, username;
-- Insert from select
INSERT INTO active_users
SELECT * FROM users WHERE is_active = true;
Select Data
Querying data from tables.
-- Basic select
SELECT * FROM users;
SELECT username, email FROM users;
-- Conditional select
SELECT * FROM users
WHERE age >= 25
AND is_active = true;
-- Order results
SELECT * FROM users
ORDER BY username ASC, created_at DESC;
-- Limit and offset
SELECT * FROM users
LIMIT 10 OFFSET 20;
-- Distinct values
SELECT DISTINCT country FROM users;
-- Count results
SELECT COUNT(*) FROM users;
SELECT COUNT(DISTINCT country) FROM users;
-- Group by
SELECT country, COUNT(*)
FROM users
GROUP BY country
HAVING COUNT(*) > 5;
Advanced Queries
Joins
Combining data from multiple tables.
-- Inner join
SELECT u.username, o.order_date
FROM users u
INNER JOIN orders o ON u.id = o.user_id;
-- Left join
SELECT u.username, o.order_date
FROM users u
LEFT JOIN orders o ON u.id = o.user_id;
-- Right join
SELECT u.username, o.order_date
FROM users u
RIGHT JOIN orders o ON u.id = o.user_id;
-- Full outer join
SELECT u.username, o.order_date
FROM users u
FULL OUTER JOIN orders o ON u.id = o.user_id;
-- Cross join
SELECT u.username, p.name
FROM users u
CROSS JOIN products p;
-- Self join
SELECT e1.name as employee, e2.name as manager
FROM employees e1
LEFT JOIN employees e2 ON e1.manager_id = e2.id;
Subqueries
Nested queries and advanced selections.
-- Subquery in WHERE
SELECT username
FROM users
WHERE id IN (
SELECT user_id
FROM orders
WHERE amount > 1000
);
-- Subquery with EXISTS
SELECT username
FROM users u
WHERE EXISTS (
SELECT 1
FROM orders o
WHERE o.user_id = u.id
);
-- Subquery in FROM
SELECT avg_order, count(*)
FROM (
SELECT user_id, AVG(amount) as avg_order
FROM orders
GROUP BY user_id
) as order_averages
GROUP BY avg_order;
-- Correlated subquery
SELECT username,
(SELECT COUNT(*)
FROM orders o
WHERE o.user_id = u.id) as order_count
FROM users u;
Data Types & Functions
Common Data Types
PostgreSQL data types and usage.
-- Numeric types
INTEGER, BIGINT, SMALLINT
DECIMAL, NUMERIC
REAL, DOUBLE PRECISION
SERIAL, BIGSERIAL -- Auto-incrementing
-- String types
CHAR(n), VARCHAR(n), TEXT
UUID -- Universally unique identifiers
-- Date/Time types
DATE -- 'YYYY-MM-DD'
TIME -- 'HH:MI:SS'
TIMESTAMP -- 'YYYY-MM-DD HH:MI:SS'
INTERVAL -- Time periods
-- Boolean type
BOOLEAN -- true/false
-- Arrays
INTEGER[]
VARCHAR[]
TEXT[]
-- JSON types
JSON, JSONB
-- Custom types
CREATE TYPE status AS ENUM ('active', 'inactive', 'pending');
Common Functions
Useful PostgreSQL functions.
-- String functions
LENGTH(string)
LOWER(string)
UPPER(string)
TRIM(string)
SUBSTRING(string, start, length)
CONCAT(string1, string2)
-- Date functions
NOW()
CURRENT_DATE
CURRENT_TIME
DATE_TRUNC('month', timestamp)
AGE(timestamp, timestamp)
EXTRACT(YEAR FROM timestamp)
-- Aggregate functions
COUNT(*)
SUM(column)
AVG(column)
MAX(column)
MIN(column)
-- Window functions
ROW_NUMBER() OVER (PARTITION BY column ORDER BY column)
RANK() OVER (ORDER BY column)
LAG(column) OVER (ORDER BY column)
Indexes & Performance
Index Management
Creating and managing indexes.
-- Create index
CREATE INDEX idx_username ON users(username);
-- Create unique index
CREATE UNIQUE INDEX idx_email ON users(email);
-- Create compound index
CREATE INDEX idx_user_status ON users(status, created_at);
-- Create partial index
CREATE INDEX idx_active_users ON users(username)
WHERE is_active = true;
-- Create expression index
CREATE INDEX idx_lower_email ON users(LOWER(email));
-- List indexes
\d tablename
-- Drop index
DROP INDEX idx_username;
-- Analyze table
ANALYZE users;
-- Show index usage
SELECT schemaname, tablename, indexname, idx_scan
FROM pg_stat_user_indexes;
Performance Analysis
Query analysis and optimization.
-- Explain query plan
EXPLAIN SELECT * FROM users WHERE email = 'test@example.com';
-- Explain and analyze
EXPLAIN ANALYZE
SELECT * FROM users
WHERE created_at >= '2023-01-01';
-- Show table statistics
SELECT relname, n_live_tup, n_dead_tup
FROM pg_stat_user_tables;
-- Show buffer cache hit ratio
SELECT
sum(heap_blks_read) as heap_read,
sum(heap_blks_hit) as heap_hit,
sum(heap_blks_hit) / (sum(heap_blks_hit) + sum(heap_blks_read)) as ratio
FROM pg_statio_user_tables;