Home› Database› Complete Guide
Complete Guide

Complete Database Tutorial

Every application needs a database. This guide covers all 147 database tutorials on TheCodeForge — SQL fundamentals, NoSQL, database design, query optimisation and more.

Learning Roadmap
Beginner → Write SQL queries, understand tables, joins and filtering
Intermediate → Design schemas, work with indexes, transactions and NoSQL
Advanced → Optimise queries, handle replication, sharding and ORMs
147
Topics
44
Beginner
60
Intermediate
43
Advanced
Jump to section
SQL Basics (16)SQL Advanced (16)NoSQL (15)Database Design (16)ORM (7)MySQL & PostgreSQL (13)PL/SQL (32)Cassandra (5)Neo4j (3)Vectors (1)OLAP (1)SQL (3)PostgreSQL (3)MySQL (8)Oracle (6)MongoDB (1)Redis (1)

Databases are the part of the stack where a small misunderstanding becomes an outage. An application bug affects one request; a missing index affects every request, and a transaction held open across a network call can stop the whole service. That asymmetry is why the fundamentals here repay attention more than almost anywhere else.

The good news is that the fundamentals are few, and they are the same across engines. An index is an ordered structure. A transaction is a promise about what other transactions can see. A join multiplies rows according to matching keys. Almost every practical question — why is this slow, why did the count double, why did this deadlock — is one of those three.

Why a query is slow: read the plan, not the query

The single most valuable database habit is running EXPLAIN before forming an opinion. The plan tells you what the optimiser decided, which is frequently not what the SQL suggests: a join order you did not write, an index ignored because statistics are stale, a sort that spilled to disk.

Four things in a plan explain most slow queries. A sequential scan where you expected an index seek. A large gap between estimated and actual row counts, which means statistics are wrong and every downstream decision was made on bad information. A nested loop over a large outer relation. And a sort or hash that did not fit in memory.

sql
-- Actual timings and row counts, not just the plan shape
EXPLAIN (ANALYZE, BUFFERS) SELECT ...;

-- The four things to look for:
--   Seq Scan where a seek was expected        -> index missing or unusable
--   rows=1 ... actual rows=480000             -> stale statistics
--   Nested Loop with a big outer relation     -> bad join strategy
--   Sort Method: external merge  Disk: 42MB   -> work_mem too small

ANALYZE orders;        -- refresh statistics before blaming the optimiser
In practiceA query that got slow overnight with no code change is usually stale statistics or a table that crossed a size threshold where the optimiser's chosen plan flipped. ANALYZE first — it is free and it is the answer surprisingly often.

Normalisation, and when to stop

Normal forms have a plain-language purpose: store each fact once, so it cannot disagree with itself. Third normal form — every non-key column depends on the key, the whole key, and nothing but the key — is the practical target for transactional systems, and going further is rarely worth it.

Denormalise deliberately, not defensively. The sequence that holds up in review: normalise, measure, and only then duplicate a column or maintain a rollup — with an explicit answer for how the copy stays correct when the source changes. A denormalised column with no update path is a future bug with a date on it.

SymptomUsually meansFix
The same value stored in several tablesUnder-normalised — updates will disagreeExtract to one table and reference it
A join on every single read pathPossibly over-normalised for the access patternMeasure first; a covering index often beats denormalising
Counts that drift from realityA maintained rollup with no transactional updateUpdate the rollup in the same transaction, or recompute
Columns named attr1, attr2…A repeating group — the classic 1NF violationA child table with one row per value

Transactions: the part everyone recites and few apply

ACID is easy to list and harder to use. The property that generates real bugs is isolation, because the default level in every mainstream database permits anomalies — and which anomalies differs by engine. PostgreSQL and SQL Server default to read committed; MySQL's InnoDB defaults to repeatable read. Code written against one and deployed on the other can behave differently with no error.

Two operational rules prevent most incidents. Keep transactions short and never hold one across a network call, because every row it touched is locked until it ends. And acquire locks in a consistent order across the codebase — deadlocks are almost always two code paths taking the same two locks in opposite orders.

Scaling: the order that actually works

Scaling decisions go wrong when they are taken out of order. The sequence that works, and that interviewers and reviewers expect: fix the queries and indexes first, because an unindexed query wastes any amount of hardware. Then add caching for read-heavy paths. Then read replicas, accepting replication lag and deciding which reads may be stale. Then partition large tables. Only then shard, because sharding changes your application's data model and removes cross-shard joins and transactions.

Each step costs more complexity than the last, and each buys more headroom. Skipping to the end is how teams acquire a distributed system to solve a missing-index problem.

Frequently Asked Questions

When should I add an index?
When a query filters, joins or sorts on a column and the plan shows a scan where a seek would serve. Not by default: every index costs write throughput and storage, because it must be maintained on every insert, update and delete. Measure, add, verify the plan changed, and remove indexes nothing uses.
SQL or NoSQL for a new project?
A relational database unless you can name the specific property that rules it out. Modern PostgreSQL handles JSON documents, full-text search and very large tables comfortably, and it gives you transactions and ad-hoc queries that you will want as requirements change. Choose NoSQL for a known, narrow access pattern at a scale that genuinely exceeds one primary.
What actually causes a deadlock?
Two transactions holding locks the other needs, in a cycle. The database detects it and kills one as the victim. The fix is almost never a configuration change — it is acquiring resources in a consistent order everywhere, keeping transactions short, and retrying the victim, since deadlocks can never be fully eliminated in a concurrent system.
How do I decide between a read replica and a cache?
A replica serves the same queries with the same freshness guarantees minus replication lag, and needs no application change beyond routing. A cache serves a specific shape of result much faster, and makes you own invalidation. Replicas for general read scaling, caches for hot well-defined results.
Is an ORM a bad idea at scale?
No, but an unexamined one is. ORMs make the easy 90% fast to write and hide the query count. Log the generated SQL in development, watch for N+1 patterns, and drop to hand-written SQL for the handful of hot queries that need it. Hybrid is the normal end state in mature codebases.
What is the single most useful thing to learn first?
Reading an execution plan. It converts every performance discussion from opinion into evidence, it is transferable across engines, and it is the skill that most reliably separates people who can fix a slow database from people who can only guess at it.

SQL Basics

SQL Advanced

NoSQL

Database Design

ORM

MySQL & PostgreSQL

PL/SQL

Introduction to PL/SQL Beginner PL/SQL Variables, Constants and Data Types Beginner PL/SQL Control Structures — IF, LOOP, WHILE Beginner PL/SQL Cursors Explained Intermediate PL/SQL Stored Procedures and Functions Intermediate PL/SQL Triggers Explained Intermediate PL/SQL Exception Handling Intermediate PL/SQL Packages Explained Advanced ORA-06512: What It Means and How to Fix It Intermediate How to Read and Understand the Oracle Error Stack (ORA-XXXX + ORA-06512) Intermediate Best Practices for Exception Handling in Oracle PL/SQL Advanced ORA-01403: No Data Found – Causes, Fixes & Prevention Beginner ORA-01422: Exact Fetch Returned More Than Requested Number of Rows Beginner ORA-06550: PL/SQL Compilation Error – The Complete Guide Beginner ORA-00942: Table or View Does Not Exist – Full Troubleshooting Beginner ORA-01017: Invalid Username/Password – Common Causes & Solutions Beginner ORA-12154: TNS: Could Not Resolve the Connect Identifier Beginner Oracle Error ORA-01858: A Non-Numeric Character Was Found Intermediate ORA-20001 to ORA-20999: User-Defined Errors and ORA-06512 Intermediate Complete List of Common Oracle Errors That Cause ORA-06512 Intermediate How to Use RAISE_APPLICATION_ERROR Properly in Oracle Intermediate Using PRAGMA EXCEPTION_INIT to Map Oracle Errors Intermediate SQL Developer Debugging Tutorial – Catch ORA-06512 Faster Intermediate Debugging PL/SQL with DBMS_OUTPUT, Exceptions & SQL Developer Intermediate Oracle PL/SQL Performance Tuning to Prevent ORA-06512 Timeouts Advanced Oracle 19c vs 21c vs 23ai: Changes in Error Handling & PL/SQL Advanced Migrating Oracle PL/SQL to PostgreSQL – Common Errors Advanced ORA-04068 and ORA-04063: Existing State of Packages Discarded / Package Has Errors Intermediate ORA-01000: Maximum Open Cursors Exceeded Intermediate ORA-06502: PL/SQL Numeric or Value Error (Character String Buffer Too Small) Beginner ORA-04063: Package Body Has Errors Intermediate PLS-00302: Component Must Be Declared Intermediate

Cassandra

Neo4j

Vectors

OLAP

SQL

PostgreSQL

MySQL

Oracle

MongoDB

Redis

Interview prep
→SQL & Database Interview
Also Explore
System Design 145 tutorials → CS Fundamentals 77 tutorials → Python 173 tutorials → Data Engineering 13 tutorials → Data Analytics 15 tutorials → PHP 56 tutorials →
Start from the beginning

Every tutorial starts with a plain-English analogy — then real code, then interview questions.

Browse Database Tutorials →