Structured Query Language — The Universal Language of Data
SELECT u.id, u.name, u.email, COUNT(o.id) AS order_count, SUM(o.total) AS total_spent FROM users u LEFT JOIN orders o ON o.user_id = u.id WHERE u.created_at >= '2024-01-01' AND u.status = 'active' GROUP BY u.id, u.name, u.email HAVING COUNT(o.id) > 0 ORDER BY total_spent DESC LIMIT 25 OFFSET 0;
-- Single row INSERT INTO products (name, price, category_id, stock) VALUES ('Mechanical Keyboard', 89.99, 4, 150); -- Multiple rows INSERT INTO tags (name, color) VALUES ('backend', '#0084ff'), ('frontend', '#00d4aa'), ('database', '#ffa500'); -- Insert from SELECT INSERT INTO archive_orders SELECT * FROM orders WHERE created_at < '2023-01-01';
UPDATE products SET price = price * 0.9, -- 10% discount updated_at = NOW() WHERE category_id = 4 AND stock > 0 AND sale_end IS NULL;
-- Delete with condition DELETE FROM sessions WHERE expires_at < NOW(); -- Delete with subquery DELETE FROM users WHERE id IN ( SELECT user_id FROM banned_users WHERE reason = 'spam' );
CREATE TABLE orders ( id BIGSERIAL PRIMARY KEY, user_id BIGINT NOT NULL REFERENCES users(id), status VARCHAR(20) NOT NULL DEFAULT 'pending', total DECIMAL(12,2) NOT NULL CHECK (total >= 0), metadata JSONB, created_at TIMESTAMP NOT NULL DEFAULT NOW(), updated_at TIMESTAMP NOT NULL DEFAULT NOW() ); CREATE INDEX idx_orders_user_status ON orders (user_id, status); CREATE INDEX idx_orders_created ON orders (created_at DESC);
ALTER TABLE users ADD COLUMN phone VARCHAR(20), ADD COLUMN verified_at TIMESTAMP, ALTER COLUMN email SET NOT NULL, DROP COLUMN legacy_id; ALTER TABLE users RENAME COLUMN username TO handle;
CREATE VIEW active_user_summary AS SELECT u.id, u.name, COUNT(o.id) AS orders, MAX(o.created_at) AS last_order FROM users u JOIN orders o ON o.user_id = u.id WHERE u.status = 'active' GROUP BY u.id, u.name;
WITH monthly_revenue AS ( SELECT DATE_TRUNC('month', created_at) AS month, SUM(total) AS revenue FROM orders WHERE status = 'completed' GROUP BY 1 ), ranked AS ( SELECT month, revenue, LAG(revenue) OVER (ORDER BY month) AS prev_revenue FROM monthly_revenue ) SELECT month, revenue, ROUND(((revenue - prev_revenue) / prev_revenue) * 100, 2) AS growth_pct FROM ranked ORDER BY month;
EXPLAIN ANALYZE SELECT u.name, COUNT(o.id) FROM users u JOIN orders o ON o.user_id = u.id GROUP BY u.id; -- Seq Scan vs Index Scan vs Hash Join -- Look for: rows estimate vs actual, loops, buffers hit -- Add index if seq scan on large table
BEGIN; -- Start transaction UPDATE accounts SET balance = balance - 500 WHERE id = 1; UPDATE accounts SET balance = balance + 500 WHERE id = 2; SAVEPOINT transfer_done; -- If something goes wrong: ROLLBACK TO transfer_done; -- On success: COMMIT;
| TINYINT | -128 to 127 | 1 byte |
| SMALLINT | -32K to 32K | 2 bytes |
| INT / INTEGER | -2B to 2B | 4 bytes |
| BIGINT | -9.2×10¹⁸ | 8 bytes |
| DECIMAL(p,s) | Exact decimal | Variable |
| FLOAT / REAL | ~7 sig digits | 4 bytes |
| DOUBLE | ~15 sig digits | 8 bytes |
| BOOLEAN | true / false | 1 byte |
| SERIAL | Auto-increment INT | PostgreSQL |
| BIGSERIAL | Auto-increment BIGINT | PostgreSQL |
| CHAR(n) | Fixed-length | Padded with spaces |
| VARCHAR(n) | Variable-length | Max n characters |
| TEXT | Unlimited string | No length limit |
| TINYTEXT | 255 chars | MySQL only |
| MEDIUMTEXT | 16MB | MySQL only |
| LONGTEXT | 4GB | MySQL only |
| BLOB | Binary large object | Binary data |
| BYTEA | Binary data | PostgreSQL |
| ENUM('a','b') | One of defined values | MySQL/PG |
| SET | Multiple enum values | MySQL |
| DATE | YYYY-MM-DD | 3 bytes |
| TIME | HH:MM:SS | 3–5 bytes |
| DATETIME | Date + Time | No timezone |
| TIMESTAMP | Unix epoch | With/without TZ |
| TIMESTAMPTZ | Timestamp + TZ | PostgreSQL |
| INTERVAL | Duration | '3 months 2 days' |
| YEAR | 1901–2155 | MySQL |
| JSON | Text JSON | Validates syntax |
| JSONB | Binary JSON | Indexable, fast |
| ARRAY | Typed arrays | PostgreSQL: int[] |
| HSTORE | Key-value store | PostgreSQL ext |
| XML | XML document | With XPath support |
| UUID | 128-bit identifier | gen_random_uuid() |
| INET | IPv4/IPv6 address | PostgreSQL |
| CIDR | Network address block | PostgreSQL |
| MACADDR | MAC address | PostgreSQL |
| POINT | Geometric point (x,y) | PostgreSQL |
| TSRANGE | Timestamp range | PostgreSQL |
| MONEY | Currency amount | Locale-dependent |
| Type | PostgreSQL | MySQL | SQLite | Notes |
|---|---|---|---|---|
| INT / BIGINT | ✓ | ✓ | ✓ | Universal support |
| DECIMAL / NUMERIC | ✓ | ✓ | ~ | SQLite uses REAL |
| TEXT / VARCHAR | ✓ | ✓ | ✓ | SQLite: TEXT for all |
| BOOLEAN | ✓ | TINYINT | INTEGER | PG has native bool |
| TIMESTAMPTZ | ✓ | ✗ | ✗ | PostgreSQL-specific |
| JSONB | ✓ | ✗ | ✗ | PG only; MySQL has JSON |
| ARRAY | ✓ | ✗ | ✗ | PostgreSQL-specific |
| UUID | ✓ | ✓ | TEXT | SQLite stores as text |
| ENUM | ✓ | ✓ | ✗ | Use CHECK in SQLite |
| INET / CIDR | ✓ | ✗ | ✗ | PostgreSQL network types |
| AUTO_INCREMENT | SERIAL/IDENTITY | ✓ | ROWID | Different syntax |
| Database | Year | Type | Creator | Notable For |
|---|---|---|---|---|
| Oracle | 1979 | Commercial RDBMS | Larry Ellison | First commercial SQL database |
| DB2 | 1983 | Commercial RDBMS | IBM | Enterprise mainframes |
| SQL Server | 1989 | Commercial RDBMS | Microsoft / Sybase | Windows enterprise standard |
| MySQL | 1995 | Open Source | Widenius / Axmark | Web applications, LAMP stack |
| PostgreSQL | 1996 | Open Source | UC Berkeley | Standards compliance, extensibility |
| SQLite | 2000 | Embedded | D. Richard Hipp | Most deployed database engine ever |