\l
or SELECT datname FROM pg_database;
\dt
\d employees
SELECT schema_name FROM information_schema.schemata;
pg_dump -s -t employees mydb
SELECT name FROM employees;
INSERT INTO employees(name, age) VALUES('John', 30);
UPDATE employees SET age = 31 WHERE name = 'John';
DELETE FROM employees WHERE name = 'John';
SELECT * FROM emp INNER JOIN dept ON emp.dept_id = dept.id;
SELECT * FROM emp LEFT JOIN dept ON emp.dept_id = dept.id;
SELECT * FROM emp RIGHT JOIN dept ON emp.dept_id = dept.id;
SELECT * FROM emp FULL JOIN dept ON emp.dept_id = dept.id;
SELECT * FROM emp CROSS JOIN dept;
SELECT data->>'name' FROM users;
CREATE TABLE employees(id SERIAL, name TEXT);
DROP TABLE employees;
ALTER TABLE employees ADD email TEXT;
SELECT * FROM employees WHERE age > 25;
SELECT * FROM employees ORDER BY age DESC;
SELECT * FROM employees ORDER BY name ASC;
SELECT * FROM employees ORDER BY salary DESC;
SELECT * FROM employees ORDER BY dept ASC, salary DESC;
SELECT dept, COUNT(*) FROM employees GROUP BY dept;
SELECT COUNT(*) FROM employees;
SELECT AVG(age) FROM employees;
SELECT SUM(salary) FROM employees;
SELECT MAX(age) FROM employees;
SELECT COALESCE(phone, 'N/A') FROM employees;
SELECT ROUND(salary, 2) FROM employees;
SELECT ROUND(salary, -3) FROM employees;
SELECT CEIL(price) FROM products;
SELECT FLOOR(price) FROM products;
SELECT price * 1.1 AS increased FROM products;
SELECT 5.0 / 2 AS result;
SELECT salary * 1.05 AS new_salary FROM employees;
SELECT NOW();
SELECT CURRENT_DATE;
SELECT CURRENT_TIME;
SELECT AGE(NOW(), '2000-01-01');
SELECT DATE_TRUNC('month', NOW());
SELECT EXTRACT(YEAR FROM NOW());
GRANT SELECT ON employees TO analyst;
REVOKE SELECT ON employees FROM analyst;
pg_dump -U username dbname > dbname.sql
\copy tablename TO 'output.csv' CSV HEADER
COPY tablename TO '/path/output.csv' DELIMITER ',' CSV HEADER;
pg_dump -s -U username dbname > schema.sql
psql -U username dbname < dbname.sql
\copy tablename FROM 'input.csv' CSV HEADER
COPY tablename FROM '/path/input.csv' DELIMITER ',' CSV HEADER;
CREATE EXTENSION parquet_fdw;
CREATE SERVER parquet_srv FOREIGN DATA WRAPPER parquet_fdw;
CREATE FOREIGN TABLE parquet_table (...) SERVER parquet_srv OPTIONS (filename '/path/file.parquet');
pgloader
, postgres_fdw
, or DB-specific tools
for migrations.SELECT data->>'name' FROM users;
SELECT * FROM users WHERE data->>'status' = 'active';
UPDATE users SET data = jsonb_set(data, '{name}', '"Omar"') WHERE id = 1;
CREATE INDEX idx_users_data ON users USING GIN (data jsonb_path_ops);
CREATE VIEW active_employees AS SELECT * FROM employees WHERE active = true;
SELECT * FROM active_employees;
DROP VIEW active_employees;
SELECT name,
(SELECT MAX(salary)
FROM employees) AS max_salary
FROM employees;
SELECT dept, avg_age
FROM (
SELECT dept, AVG(age) AS avg_age
FROM employees
GROUP BY dept
) AS dept_ages;
SELECT *
FROM employees
WHERE salary > (SELECT AVG(salary)
FROM employees);
SELECT name
FROM employees e
WHERE salary > (SELECT AVG(salary)
FROM employees
WHERE dept = e.dept);
SELECT DISTINCT dept FROM employees;
SELECT * FROM employees LIMIT 5 OFFSET 10;
SELECT name FROM a UNION SELECT name FROM b;
SELECT name FROM employees WHERE EXISTS (SELECT 1 FROM dept WHERE dept.id = employees.dept_id);
SELECT * FROM employees WHERE dept IN ('HR', 'IT');
SELECT * FROM employees WHERE age BETWEEN 20 AND 30;
SELECT * FROM employees WHERE name LIKE 'A%';
SELECT name, CASE WHEN age > 30 THEN 'Senior' ELSE 'Junior' END FROM employees;
SELECT '123'::INTEGER;
SELECT * FROM employees WHERE email IS NULL;
CREATE TABLE t (id SERIAL, active BOOLEAN DEFAULT true);
CREATE TABLE t (id SERIAL PRIMARY KEY);
CREATE TABLE orders (user_id INT REFERENCES users(id));
SELECT dept, AVG(salary) AS avg_salary
FROM employees
WHERE salary > 50000
GROUP BY dept;
SELECT dept, AVG(salary) AS avg_salary
FROM employees
GROUP BY dept
HAVING avg_salary > 60000;
WHERE
cannot use avg_salary
because aliases are not available until after the SELECT clause is processed. HAVING
can use avg_salary
because it is evaluated after aggregation and SELECT.
CREATE TABLE t (id SERIAL PRIMARY KEY);
CREATE TABLE t (email TEXT UNIQUE);
CREATE TABLE t (age INT CHECK (age >= 18));
CREATE INDEX idx_name ON employees(name);
EXPLAIN SELECT * FROM employees;
ANALYZE employees;
WITH recent AS (SELECT * FROM employees WHERE hired > '2024-01-01') SELECT * FROM recent;
INSERT INTO employees(name) VALUES('Anna') RETURNING id;