BaseCodeByte
PgSQL

PostgreSQL Lessons

Go deep into PostgreSQL with relational modeling, advanced SQL, JSONB, arrays, indexing and full-text search.

Course outline

Tracks and lessons

Track 01beginner

PostgreSQL Fundamentals

Go deep into POSTGRESQL with relational modeling, advanced SQL, JSONB, arrays, indexing, full-text search.

01Introduction to PostgreSQLWhat is PostgreSQL? PostgreSQL (often called Postgres ) is a powerful, open-source object-relational database system. It has over 35. ACID Compliant — Guarantees data integrity Extensible — Custom types, functions, operators -- Using psql command-linbeginner

What is PostgreSQL? PostgreSQL (often called Postgres ) is a powerful, open-source object-relational database system. It has over 35. ACID Compliant — Guarantees data integrity Extensible — Custom types, functions, operators -- Using psql command-lin

Example
-- Using psql command-line tool
psql -U postgres -d mydb

-- Connection string format
postgresql://user:password@host:5432/database

-- Common psql meta-commands
l          -- list databases
c mydb     -- connect to database
dt         -- list tables
d table    -- describe table
q          -- quit
Quiz

What does ACID stand for in database terminology?

Which PostgreSQL data type stores JSON in binary format with indexing support?

Which psql command lists all databases?

02SELECT StatementThe SELECT Statement SELECT retrieves data from one or more tables. PostgreSQL's SELECT is very powerful with many optional. SELECT column1, column2, ... FROM table_name [WHERE condition] [GROUP BY columns] [HAVING condition] [ORDER BY columns] [LIMIbeginner

The SELECT Statement SELECT retrieves data from one or more tables. PostgreSQL's SELECT is very powerful with many optional. SELECT column1, column2, ... FROM table_name [WHERE condition] [GROUP BY columns] [HAVING condition] [ORDER BY columns] [LIMI

Example
SELECT column1, column2, ...
FROM table_name
[WHERE condition]
[GROUP BY columns]
[HAVING condition]
[ORDER BY columns]
[LIMIT count]
[OFFSET skip];
Quiz

Which clause removes duplicate rows from query results?

What keyword creates a column alias?

What does SELECT * return?

03WHERE & FilteringWHERE Clause The WHERE clause filters rows based on conditions. PostgreSQL supports rich comparison and logical operators. SELECT * FROM employees WHERE salary > 70000; SELECT * FROM employees WHERE department = 'Engineering'; SELECT * FROM employeesbeginner

WHERE Clause The WHERE clause filters rows based on conditions. PostgreSQL supports rich comparison and logical operators. SELECT * FROM employees WHERE salary > 70000; SELECT * FROM employees WHERE department = 'Engineering'; SELECT * FROM employees

Example
SELECT * FROM employees WHERE salary > 70000;
SELECT * FROM employees WHERE department = 'Engineering';
SELECT * FROM employees WHERE hire_date >= '2022-01-01';
SELECT * FROM employees WHERE status != 'inactive';  -- or <>
Quiz

Which PostgreSQL-specific LIKE variant is case-insensitive?

SELECT * FROM t WHERE x BETWEEN 10 AND 20 — is 10 included?

How do you check if a column has no value in PostgreSQL?

04ORDER BY & LIMITORDER BY — Sorting Results ORDER BY sorts query results. You can sort by one or multiple columns, ascending or descending. -- Ascending (default) SELECT * FROM employees ORDER BY last_name; SELECT * FROM employees ORDER BY last_name ASC; -- Descendinbeginner

ORDER BY — Sorting Results ORDER BY sorts query results. You can sort by one or multiple columns, ascending or descending. -- Ascending (default) SELECT * FROM employees ORDER BY last_name; SELECT * FROM employees ORDER BY last_name ASC; -- Descendin

Example
-- Ascending (default)
SELECT * FROM employees ORDER BY last_name;
SELECT * FROM employees ORDER BY last_name ASC;

-- Descending
SELECT * FROM employees ORDER BY salary DESC;

-- Multiple columns
SELECT * FROM employees
ORDER BY department ASC, salary DESC;
Quiz

What is the default sort order in ORDER BY?

To get items 11-20, what LIMIT/OFFSET should you use?

Which keyword controls NULL position in ORDER BY in PostgreSQL?

Track 02beginner

Data Types & Table Design

Go deep into POSTGRESQL with relational modeling, advanced SQL, JSONB, arrays, indexing, full-text search.

01PostgreSQL Data TypesPostgreSQL Data Types PostgreSQL has a rich type system. Choosing the right type improves storage efficiency and query performance. -- Integer types SMALLINT -- 2 bytes, -32768 to 32767 INTEGER / INT -- 4 bytes, ~±2.1 billion BIGINT -- 8 bytes, ~±9.2beginner

PostgreSQL Data Types PostgreSQL has a rich type system. Choosing the right type improves storage efficiency and query performance. -- Integer types SMALLINT -- 2 bytes, -32768 to 32767 INTEGER / INT -- 4 bytes, ~±2.1 billion BIGINT -- 8 bytes, ~±9.2

Example
-- Integer types
SMALLINT        -- 2 bytes, -32768 to 32767
INTEGER / INT   -- 4 bytes, ~±2.1 billion
BIGINT          -- 8 bytes, ~±9.2 quintillion

-- Auto-increment (serial types)
SMALLSERIAL     -- 2-byte auto-increment
SERIAL          -- 4-byte auto-increment
BIGSERIAL       -- 8-byte auto-increment

-- Exact decimal (financial data)
NUMERIC(10, 2)  -- 10 digits total, 2 decimal places
DECIMAL(10, 2)  -- Same as NUMERIC

-- Floating point (approximate)
REAL            -- 4 bytes, 6 decimal digits precision
DOUBLE PRECISION -- 8 bytes, 15 decimal digits precision
Quiz

Which type should you prefer for storing money/financial data in PostgreSQL?

What is the advantage of JSONB over JSON in PostgreSQL?

Which timestamp type stores timezone information?

02CREATE TABLECREATE TABLE PostgreSQL's CREATE TABLE is more powerful than most databases, supporting rich constraints, defaults, and inheritance. CREATE TABLE table_name ( column1 datatype [constraints], column2 datatype [constraints], ... [table_constraints] );beginner

CREATE TABLE PostgreSQL's CREATE TABLE is more powerful than most databases, supporting rich constraints, defaults, and inheritance. CREATE TABLE table_name ( column1 datatype [constraints], column2 datatype [constraints], ... [table_constraints] );

Example
CREATE TABLE table_name (
  column1  datatype  [constraints],
  column2  datatype  [constraints],
  ...
  [table_constraints]
);
Quiz

Which keyword prevents error when table already exists?

Which auto-increment type uses 8 bytes in PostgreSQL?

What does INHERITS do in PostgreSQL CREATE TABLE?

03ConstraintsPostgreSQL Constraints Constraints enforce data integrity rules at the database level. They cannot be violated by any INSERT. -- Column-level CREATE TABLE users ( id SERIAL PRIMARY KEY, ... ); -- Composite primary key CREATE TABLE order_items ( orderbeginner

PostgreSQL Constraints Constraints enforce data integrity rules at the database level. They cannot be violated by any INSERT. -- Column-level CREATE TABLE users ( id SERIAL PRIMARY KEY, ... ); -- Composite primary key CREATE TABLE order_items ( order

Example
-- Column-level
CREATE TABLE users (
  id SERIAL PRIMARY KEY,
  ...
);

-- Composite primary key
CREATE TABLE order_items (
  order_id    INT,
  product_id  INT,
  quantity    INT,
  PRIMARY KEY (order_id, product_id)
);
Quiz

What does ON DELETE CASCADE do on a foreign key?

Which constraint type is unique to PostgreSQL and prevents overlapping ranges?

Which ON DELETE option prevents deletion if child rows exist?

Track 03beginner

Joins & Relationships

Go deep into POSTGRESQL with relational modeling, advanced SQL, JSONB, arrays, indexing, full-text search.

01Understanding JoinsSQL Joins in PostgreSQL Joins combine rows from two or more tables based on a related column. They are fundamental. -- Departments table CREATE TABLE departments ( id SERIAL PRIMARY KEY, name TEXT NOT NULL ); INSERT INTO departments VALUES (1, 'Enginbeginner

SQL Joins in PostgreSQL Joins combine rows from two or more tables based on a related column. They are fundamental. -- Departments table CREATE TABLE departments ( id SERIAL PRIMARY KEY, name TEXT NOT NULL ); INSERT INTO departments VALUES (1, 'Engin

Example
-- Departments table
CREATE TABLE departments (
  id   SERIAL PRIMARY KEY,
  name TEXT NOT NULL
);

INSERT INTO departments VALUES
  (1, 'Engineering'),
  (2, 'Marketing'),
  (3, 'HR'),
  (4, 'Finance');  -- no employees

-- Employees table
CREATE TABLE employees (
  id          SERIAL PRIMARY KEY,
  name        TEXT NOT NULL,
  dept_id     INT REFERENCES departments(id)
);

INSERT INTO employees VALUES
  (1, 'Alice',  1),  -- Engineering
  (2, 'Bob',    2),  -- Marketing
  (3, 'Carol',  1),  -- Engineering
  (4, 'Dave',   NULL), -- no department
  (5, 'Eve',    5);  -- non-existent dept
Quiz

Which join returns all rows from both tables, with NULLs where there is no match?

CROSS JOIN produces how many rows from tables of 3 and 4 rows?

Which join is also called an "equi-join"?

02INNER JOININNER JOIN INNER JOIN returns only rows where the join condition matches in BOTH tables. Non-matching rows are. -- Get employees with their department names SELECT e.name, d.name AS department FROM employees e INNER JOIN departments d ON e.dept_id = beginner

INNER JOIN INNER JOIN returns only rows where the join condition matches in BOTH tables. Non-matching rows are. -- Get employees with their department names SELECT e.name, d.name AS department FROM employees e INNER JOIN departments d ON e.dept_id =

Example
-- Get employees with their department names
SELECT e.name, d.name AS department
FROM employees e
INNER JOIN departments d ON e.dept_id = d.id;

-- Result: only employees with a valid dept_id
-- Alice | Engineering
-- Bob   | Marketing
-- Carol | Engineering
Quiz

What happens to rows with no matching row in an INNER JOIN?

What is USING in a JOIN?

SELECT * FROM a JOIN b ON a.id = b.id — "JOIN" without a prefix means?

03LEFT, RIGHT & FULL OUTER JOINOuter Joins Outer joins preserve non-matching rows from one or both tables, filling gaps with NULL. -- All employees, even those without a department SELECT e.name, d.name AS department FROM employees e LEFT JOIN departments d ON e.dept_id = d.id; --intermediate

Outer Joins Outer joins preserve non-matching rows from one or both tables, filling gaps with NULL. -- All employees, even those without a department SELECT e.name, d.name AS department FROM employees e LEFT JOIN departments d ON e.dept_id = d.id; --

Example
-- All employees, even those without a department
SELECT e.name, d.name AS department
FROM employees e
LEFT JOIN departments d ON e.dept_id = d.id;

-- Result:
-- Alice | Engineering
-- Bob   | Marketing
-- Carol | Engineering
-- Dave  | NULL          ← Dave has no dept
Quiz

Which join returns all departments even if they have no employees?

How do you find rows in table A with NO match in table B using LEFT JOIN?

FULL OUTER JOIN returns which rows?

Track 04intermediate

Advanced Queries

Go deep into POSTGRESQL with relational modeling, advanced SQL, JSONB, arrays, indexing, full-text search.

01GROUP BY & Aggregate FunctionsGROUP BY & Aggregate Functions GROUP BY groups rows with the same values and applies aggregate functions to each group. SELECT COUNT(*) AS total_rows, COUNT(salary) AS non_null_salaries, COUNT(DISTINCT dept) AS unique_depts, SUM(salary) AS total_salaintermediate

GROUP BY & Aggregate Functions GROUP BY groups rows with the same values and applies aggregate functions to each group. SELECT COUNT(*) AS total_rows, COUNT(salary) AS non_null_salaries, COUNT(DISTINCT dept) AS unique_depts, SUM(salary) AS total_sala

Example
SELECT
  COUNT(*)              AS total_rows,
  COUNT(salary)         AS non_null_salaries,
  COUNT(DISTINCT dept)  AS unique_depts,
  SUM(salary)           AS total_salary,
  AVG(salary)           AS average_salary,
  MIN(salary)           AS min_salary,
  MAX(salary)           AS max_salary,
  ROUND(AVG(salary), 2) AS avg_rounded
FROM employees;
Quiz

What is the difference between WHERE and HAVING?

Which aggregate function concatenates strings from multiple rows?

To get a grand total alongside subtotals in GROUP BY, use:

02Window FunctionsWindow Functions Window functions perform calculations across a set of rows related to the current row — without. function_name() OVER ( [PARTITION BY column, ...] [ORDER BY column, ...] [ROWS/RANGE frame_spec] )intermediate

Window Functions Window functions perform calculations across a set of rows related to the current row — without. function_name() OVER ( [PARTITION BY column, ...] [ORDER BY column, ...] [ROWS/RANGE frame_spec] )

Example
function_name() OVER (
  [PARTITION BY column, ...]
  [ORDER BY column, ...]
  [ROWS/RANGE frame_spec]
)
Quiz

Which window function assigns no gaps for ties?

What does PARTITION BY do in a window function?

LAG() in a window function returns:

03CTEs — Common Table ExpressionsCommon Table Expressions (CTEs) CTEs define temporary named result sets that exist for the duration of a query. They make. -- WITH clause defines the CTE WITH high_earners AS ( SELECT name, salary, department FROM employees WHERE salary > 80000 ) SELintermediate

Common Table Expressions (CTEs) CTEs define temporary named result sets that exist for the duration of a query. They make. -- WITH clause defines the CTE WITH high_earners AS ( SELECT name, salary, department FROM employees WHERE salary > 80000 ) SEL

Example
-- WITH clause defines the CTE
WITH high_earners AS (
  SELECT name, salary, department
  FROM employees
  WHERE salary > 80000
)
SELECT department, COUNT(*) AS count, AVG(salary) AS avg
FROM high_earners
GROUP BY department;
Quiz

What does WITH RECURSIVE enable in PostgreSQL?

Can PostgreSQL CTEs contain DELETE statements?

Where is a CTE visible in a query?

04SubqueriesSubqueries A subquery is a query nested inside another query. They can appear in SELECT, FROM, WHERE. -- Employees earning above overall average SELECT name, salary, (SELECT AVG(salary) FROM employees) AS company_avg FROM employees WHERE salary > (SEintermediate

Subqueries A subquery is a query nested inside another query. They can appear in SELECT, FROM, WHERE. -- Employees earning above overall average SELECT name, salary, (SELECT AVG(salary) FROM employees) AS company_avg FROM employees WHERE salary > (SE

Example
-- Employees earning above overall average
SELECT name, salary,
       (SELECT AVG(salary) FROM employees) AS company_avg
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);
Quiz

What does EXISTS return?

What is a LATERAL JOIN used for in PostgreSQL?

A scalar subquery must return:

Track 05intermediate

PostgreSQL Features

Go deep into POSTGRESQL with relational modeling, advanced SQL, JSONB, arrays, indexing, full-text search.

01JSON & JSONBJSON and JSONB in PostgreSQL PostgreSQL has two JSON types: JSON (stored as text, preserves formatting) and JSONB (binary, indexed, faster. CREATE TABLE products ( id SERIAL PRIMARY KEY, name TEXT NOT NULL, attrs JSONB, -- flexible attributes tags TEintermediate

JSON and JSONB in PostgreSQL PostgreSQL has two JSON types: JSON (stored as text, preserves formatting) and JSONB (binary, indexed, faster. CREATE TABLE products ( id SERIAL PRIMARY KEY, name TEXT NOT NULL, attrs JSONB, -- flexible attributes tags TE

Example
CREATE TABLE products (
  id       SERIAL PRIMARY KEY,
  name     TEXT NOT NULL,
  attrs    JSONB,          -- flexible attributes
  tags     TEXT[],         -- array for simple tags
  metadata JSONB
);

INSERT INTO products (name, attrs, tags) VALUES
  ('Widget Pro',
   '{"color": "blue", "weight": 1.5, "dimensions": {"w": 10, "h": 5}}',
   ARRAY['electronics', 'gadget']);
Quiz

What is the difference between -> and ->> in JSONB?

Which operator checks if a JSONB value contains another JSON?

Which index type should you create on a JSONB column for @> queries?

02ArraysPostgreSQL Arrays PostgreSQL supports native array types — any data type can be stored as an array. Arrays. CREATE TABLE articles ( id SERIAL PRIMARY KEY, title TEXT NOT NULL, tags TEXT[], -- array of text scores INTEGER[], -- array of integers matriintermediate

PostgreSQL Arrays PostgreSQL supports native array types — any data type can be stored as an array. Arrays. CREATE TABLE articles ( id SERIAL PRIMARY KEY, title TEXT NOT NULL, tags TEXT[], -- array of text scores INTEGER[], -- array of integers matri

Example
CREATE TABLE articles (
  id       SERIAL PRIMARY KEY,
  title    TEXT NOT NULL,
  tags     TEXT[],           -- array of text
  scores   INTEGER[],        -- array of integers
  matrix   INTEGER[][]       -- 2D array
);

-- Inserting arrays
INSERT INTO articles (title, tags, scores) VALUES
  ('PostgreSQL Tips', ARRAY['database', 'sql', 'tips'], ARRAY[95, 87, 92]),
  ('JavaScript Guide', '{javascript, web, frontend}', '{88, 90, 85}');
Quiz

PostgreSQL arrays are indexed starting at:

Which operator checks if ANY element of the search array exists in the column array?

Which function expands an array into individual rows?

03Full-Text SearchFull-Text Search PostgreSQL has built-in full-text search — faster than LIKE '%query%', supports stemming, ranking, and highlighting. -- tsvector: preprocessed document SELECT to_tsvector('english', 'PostgreSQL is a powerful database system'); -- 'daintermediate

Full-Text Search PostgreSQL has built-in full-text search — faster than LIKE '%query%', supports stemming, ranking, and highlighting. -- tsvector: preprocessed document SELECT to_tsvector('english', 'PostgreSQL is a powerful database system'); -- 'da

Example
-- tsvector: preprocessed document
SELECT to_tsvector('english', 'PostgreSQL is a powerful database system');
-- 'databas':5 'power':4 'postgresql':1 'system':6
-- (stops words removed, stems applied)

-- tsquery: search query
SELECT to_tsquery('english', 'database & powerful');
SELECT plainto_tsquery('english', 'powerful database');
Quiz

What does to_tsvector() do?

Which index type should be used for full-text search columns?

The setweight() function in full-text search is used for:

04Indexes & Query PerformanceIndexes & Query Performance Indexes dramatically speed up queries by allowing PostgreSQL to find rows without scanning the entire table. -- B-tree: default, range queries, equality, sorting CREATE INDEX idx_employees_salary ON employees(salary); CREAadvanced

Indexes & Query Performance Indexes dramatically speed up queries by allowing PostgreSQL to find rows without scanning the entire table. -- B-tree: default, range queries, equality, sorting CREATE INDEX idx_employees_salary ON employees(salary); CREA

Example
-- B-tree: default, range queries, equality, sorting
CREATE INDEX idx_employees_salary ON employees(salary);
CREATE INDEX idx_employees_name ON employees(last_name, first_name);

-- Hash: only equality checks (rarely needed)
CREATE INDEX idx_hash_email ON users USING HASH (email);

-- GIN: arrays, JSONB, full-text search
CREATE INDEX idx_products_attrs ON products USING GIN (attrs);
CREATE INDEX idx_articles_tags  ON articles USING GIN (tags);

-- BRIN: very large tables with natural ordering (timestamps, sequential IDs)
CREATE INDEX idx_logs_created ON logs USING BRIN (created_at);

-- GiST: geometric types, ranges, full-text with ranking
CREATE INDEX idx_events_range ON events USING GIST (during);
Quiz

Which index type is best for JSONB and array columns?

What is a partial index?

Which EXPLAIN output type indicates no table heap access is needed?

Track 06advanced

Functions, Triggers & Admin

Go deep into POSTGRESQL with relational modeling, advanced SQL, JSONB, arrays, indexing, full-text search.

01PL/pgSQL FunctionsPL/pgSQL Functions PostgreSQL's procedural language PL/pgSQL allows you to write functions with variables, loops, conditions, and error handling. CREATE OR REPLACE FUNCTION add_numbers(a INTEGER, b INTEGER) RETURNS INTEGER AS $$ BEGIN RETURN a + b; Eadvanced

PL/pgSQL Functions PostgreSQL's procedural language PL/pgSQL allows you to write functions with variables, loops, conditions, and error handling. CREATE OR REPLACE FUNCTION add_numbers(a INTEGER, b INTEGER) RETURNS INTEGER AS $$ BEGIN RETURN a + b; E

Example
CREATE OR REPLACE FUNCTION add_numbers(a INTEGER, b INTEGER)
RETURNS INTEGER AS $$
BEGIN
  RETURN a + b;
END;
$$ LANGUAGE plpgsql;

-- Call it
SELECT add_numbers(10, 20);  -- 30
Quiz

What language is used for PostgreSQL stored procedures?

Which clause in PL/pgSQL declares local variables?

How do you raise an error in PL/pgSQL?

02TriggersTriggers Triggers automatically execute a function when a specified database event occurs (INSERT, UPDATE, DELETE, or TRUNCATE). -- BEFORE: fires before the operation, can modify NEW -- AFTER: fires after the operation, useful for auditing -- INSTEADadvanced

Triggers Triggers automatically execute a function when a specified database event occurs (INSERT, UPDATE, DELETE, or TRUNCATE). -- BEFORE: fires before the operation, can modify NEW -- AFTER: fires after the operation, useful for auditing -- INSTEAD

Example
-- BEFORE: fires before the operation, can modify NEW
-- AFTER: fires after the operation, useful for auditing
-- INSTEAD OF: for views

-- FOR EACH ROW: fires once per affected row
-- FOR EACH STATEMENT: fires once per SQL statement
Quiz

Which TG_ variable contains the new row values in an INSERT trigger?

What timing must you use to modify NEW before it is saved?

What must a BEFORE ROW trigger return to allow the operation to proceed?

03Transactions & LockingTransactions & Locking Transactions ensure data integrity by grouping operations into atomic units. PostgreSQL has excellent transaction support. -- Start transaction BEGIN; UPDATE accounts SET balance = balance - 500 WHERE id = 1; UPDATE accounts SEadvanced

Transactions & Locking Transactions ensure data integrity by grouping operations into atomic units. PostgreSQL has excellent transaction support. -- Start transaction BEGIN; UPDATE accounts SET balance = balance - 500 WHERE id = 1; UPDATE accounts SE

Example
-- Start transaction
BEGIN;

UPDATE accounts SET balance = balance - 500 WHERE id = 1;
UPDATE accounts SET balance = balance + 500 WHERE id = 2;

-- Commit if all good
COMMIT;

-- Or rollback on error
ROLLBACK;
Quiz

What does SAVEPOINT allow you to do?

Which isolation level prevents all concurrency anomalies?

FOR UPDATE SKIP LOCKED is useful for:

04Views & Materialized ViewsViews & Materialized Views Views are saved queries that act like virtual tables. Materialized views store the query results physically. -- Create a view CREATE VIEW active_employees AS SELECT e.id, e.name, e.salary, d.name AS department FROM employeeadvanced

Views & Materialized Views Views are saved queries that act like virtual tables. Materialized views store the query results physically. -- Create a view CREATE VIEW active_employees AS SELECT e.id, e.name, e.salary, d.name AS department FROM employee

Example
-- Create a view
CREATE VIEW active_employees AS
SELECT e.id, e.name, e.salary, d.name AS department
FROM employees e
JOIN departments d ON e.dept_id = d.id
WHERE e.is_active = TRUE;

-- Query it like a table
SELECT * FROM active_employees WHERE department = 'Engineering';

-- Drop a view
DROP VIEW active_employees;

-- Create or replace
CREATE OR REPLACE VIEW active_employees AS
SELECT ...;
Quiz

What must you do to update data in a materialized view?

WITH CHECK OPTION on a view does what?

Which is better for a pre-computed monthly report dashboard?