Help improve SovranCode?

Google Analytics can measure anonymous usage after you choose Allow. Essential account and progress features work either way.

SovranCode
SQL: Query, Model, and Analyze Data Databases, SQL, and the Relational Model
This device
Course contentsDatabases, SQL, and the Relational Model · 32 topics

Relational foundations

Databases, SQL, and the relational modelTables, rows, columns, and schemasData types and NULLPrimary keys, foreign keys, and relationships

Reading and filtering data

Your first SELECT queryConditions with WHERESorting, limiting, and distinct valuesText, dates, patterns, and conditional results

Reports, aggregation, and analytics

Aggregate functionsGROUP BY and HAVINGWindow functionsCommon table expressions

Combining related data

INNER, LEFT, RIGHT, and FULL joinsPlannedSelf joins and many-to-many dataPlannedSubqueries and correlated subqueriesPlannedUNION, INTERSECT, and EXCEPTPlanned

Designing reliable schemas

CREATE TABLE and schema designPlannedConstraints and data integrityPlannedNormalization and intentional denormalizationPlannedViews and materialized viewsPlanned

Writing and protecting data

INSERT, UPDATE, and DELETEPlannedUpserts and conflict handlingPlannedTransactions and savepointsPlannedIsolation, locks, and concurrencyPlanned

Performance and administration

Indexes and access pathsPlannedEXPLAIN and query plansPlannedQuery tuning patternsPlannedBackups, restores, and migrationsPlanned

Security and production workflow

Users, roles, and least privilegePlannedPreventing SQL injectionPlannedStored procedures, functions, and triggersPlannedProduction data projectPlanned
SQL: Query, Model, and Analyze Data12 complete · 20 planned

Relational foundations

Databases, SQL, and the relational modelTables, rows, columns, and schemasData types and NULLPrimary keys, foreign keys, and relationships

Reading and filtering data

Your first SELECT queryConditions with WHERESorting, limiting, and distinct valuesText, dates, patterns, and conditional results

Reports, aggregation, and analytics

Aggregate functionsGROUP BY and HAVINGWindow functionsCommon table expressions

Combining related data

INNER, LEFT, RIGHT, and FULL joinsPlannedSelf joins and many-to-many dataPlannedSubqueries and correlated subqueriesPlannedUNION, INTERSECT, and EXCEPTPlanned

Designing reliable schemas

CREATE TABLE and schema designPlannedConstraints and data integrityPlannedNormalization and intentional denormalizationPlannedViews and materialized viewsPlanned

Writing and protecting data

INSERT, UPDATE, and DELETEPlannedUpserts and conflict handlingPlannedTransactions and savepointsPlannedIsolation, locks, and concurrencyPlanned

Performance and administration

Indexes and access pathsPlannedEXPLAIN and query plansPlannedQuery tuning patternsPlannedBackups, restores, and migrationsPlanned

Security and production workflow

Users, roles, and least privilegePlannedPreventing SQL injectionPlannedStored procedures, functions, and triggersPlannedProduction data projectPlanned
COURSE OVERVIEWSQL: Query, Model, and Analyze Data
NEXT LESSONTables, Rows, Columns, and Schemas
SQL foundations 90 min

Databases, SQL, and the Relational Model

SQL becomes much easier when you understand the system it describes. In this lesson, you will build an in-memory relational database, identify tables, rows, columns, schemas, keys, and relationships, run real queries, and explain why SQL asks for a result instead of prescribing every execution step.

What you will leave with

You will be able to distinguish a database from a database management system and the SQL language, model a small entity as a table, explain schema versus stored data, choose a stable primary key, connect tables with a foreign key, read a simple CREATE TABLE, INSERT, and SELECT workflow, and run isolated SQL safely in your browser.

Build the mental model before memorizing statements

Database systemSeparate the stored database, the DBMS that manages it, and SQL used to communicate with it.
Relational structureRead tables as sets of records whose columns have explicit names, meanings, and constraints.
Identity and relationshipsUse primary and foreign keys to connect records without copying descriptive values everywhere.
Declarative queriesDescribe the result you need and let the database engine choose a valid execution plan.

Database, DBMS, and SQL are different things

A database is an organized collection of data plus the structures that give that data meaning. A database management system, or DBMS, is the software responsible for storing that database, coordinating readers and writers, enforcing rules, recovering work, and answering queries. PostgreSQL, MySQL, SQLite, SQL Server, and Oracle Database are DBMS products or engines. SQL is the language used to define, query, and change relational data through those systems.

The distinction is practical. If a query is valid SQL but uses a function that only PostgreSQL implements, portability is a language-dialect concern. If two users change the same row simultaneously, coordination belongs to the DBMS. If a foreign key rejects a nonexistent department, the rule belongs to the database schema and is enforced by the DBMS.

01

Database

Tables, records, relationships, indexes, and rules persisted as one organized data system.

02

DBMS

The engine that stores, validates, protects, plans, coordinates, and recovers the database.

03

SQL

The declarative language you use to define structures and request or change data.

SQL is declarative

With SELECT, you describe the columns, rows, relationships, and ordering you want. You normally do not specify every disk read or loop. The database planner chooses an execution strategy, which is why the same query can keep its meaning while an index changes its performance.

The relational model organizes facts through relations

In everyday SQL, a relation is represented by a table. A table models one kind of entity or fact: students, courses, departments, purchases, or enrollments. Each row represents one occurrence. Each column represents one named attribute with an intended domain of allowed values. A well-designed table has a clear sentence behind it—for example, “one row represents one learning path.”

The formal relational model and practical SQL are not identical. Mathematical relations do not contain duplicate tuples and have no inherent order. SQL tables may permit duplicate-looking rows unless keys or constraints prevent them, query results can preserve duplicates, and SQL adds NULL for missing or unknown information. Treat ordering as explicit: without ORDER BY, the DBMS does not promise the order in which rows appear.

Departments and courses tables connected through a primary key and foreign key, followed by a joined SQL result
One relationship, three views. The source tables store each fact once. The key columns preserve the connection. A query follows that connection and returns a readable result without copying the department name into every course row.
01

Identify each entity

departments and courses describe different kinds of things, so they belong in separate tables.

02

Give rows stable identity

departments.id uniquely identifies a department even when its display name changes.

03

Store the relationship

courses.department_id records which department owns each course and can be checked by a foreign-key constraint.

04

Build the result on demand

A JOIN matches equal key values so the report can show course and department names together.

learning_pathsOne table, three rows, three columns
idnamelevel
1HTMLBeginner
2JavaScriptIntermediate
3SQLBeginner
Row: one learning pathColumn: one attributeCell: one value at their intersection

Create and query a first database

The notebook below runs real SQLite-compatible SQL inside an isolated browser worker. Every run creates a new in-memory database, executes the statements in order, prints the result set, then discards the database. Change the inserted names or add a fourth row. Run again and compare the result with your prediction.

SQL BROWSER RUNNER

Create, insert, and select

Define one table, insert three rows, and request a predictable result. The database exists only for this run.

CREATE TABLE learning_paths (
  id INTEGER PRIMARY KEY,
  name TEXT NOT NULL,
  level TEXT NOT NULL
);

INSERT INTO learning_paths (id, name, level) VALUES
  (1, 'HTML', 'Beginner'),
  (2, 'JavaScript', 'Intermediate'),
  (3, 'SQL', 'Beginner');

SELECT id, name, level
FROM learning_paths
ORDER BY id;
QUERY OUTPUT
Edit the query, predict the rows it will return, then run it.

Each run starts a fresh SQLite database in an isolated browser worker. Your edited SQL is saved on this device, but the database and its rows are discarded after the run.

Try this next: Add a fourth learning path, run the query again, and explain why its position is predictable.

CREATE TABLE defines the schema. INSERT creates rows that obey that schema. SELECT produces a result set. These labels are often described as data definition, data manipulation, and data query language. The labels are useful for learning, though database documentation may categorize statements differently.

  1. 01
    Define structure

    CREATE TABLE names the table, columns, types, and constraints.

  2. 02
    Store valid records

    INSERT supplies rows whose values must satisfy the declared rules.

  3. 03
    Request a result

    SELECT chooses the attributes and rows that answer a question.

  4. 04
    Order deliberately

    ORDER BY makes presentation order part of the request instead of relying on an accident.

Schema and data change at different speeds

The schema is the durable description of structure: table and column names, types, keys, constraints, defaults, and relationships. The current rows are the database’s changing state, sometimes called an instance or snapshot. Applications add and modify rows constantly; schema changes should be planned because every existing and future row must fit the new structure.

Run this example to inspect SQLite’s own schema catalog and then inspect the rows. Change the UNIQUE email rule or add a column definition, reset the notebook when needed, and observe how the schema text differs from the result data.

SQL BROWSER RUNNER

Inspect structure and stored rows

The first result describes the table definition. The second result contains the current student records.

CREATE TABLE students (
  id INTEGER PRIMARY KEY,
  email TEXT NOT NULL UNIQUE,
  joined_on TEXT NOT NULL
);

INSERT INTO students (id, email, joined_on) VALUES
  (101, 'ada@example.test', '2026-09-01'),
  (102, 'linus@example.test', '2026-09-03');

SELECT name, sql
FROM sqlite_schema
WHERE type = 'table'
ORDER BY name;

SELECT * FROM students ORDER BY id;
QUERY OUTPUT
Edit the query, predict the rows it will return, then run it.

Each run starts a fresh SQLite database in an isolated browser worker. Your edited SQL is saved on this device, but the database and its rows are discarded after the run.

Try this next: Add an optional nickname column and compare its schema definition with the stored row values.

Types are not identical across engines

SQLite uses flexible type affinity, while PostgreSQL and other systems enforce types differently and expose different built-in types. The relational ideas transfer; exact type names, automatic identifiers, functions, and administrative syntax require the documentation for your chosen DBMS.

Keys give rows identity and relationships meaning

A primary key identifies one row inside its table. Good keys are unique, non-null, and stable. A user-facing value such as a department name may be unique today but can change later. A separate identifier lets the name change without rewriting every relationship that refers to the department.

A foreign key stores the primary-key value of a related row and asks the DBMS to protect that reference. In the example, many courses can point to one department. The department name is stored once; each course stores only department_id. The JOIN reconstructs a useful combined result when it is needed.

SQL BROWSER RUNNER

Connect courses to departments

Run the same departments-and-courses model shown in the illustration, then inspect the joined result.

PRAGMA foreign_keys = ON;

CREATE TABLE departments (
  id INTEGER PRIMARY KEY,
  name TEXT NOT NULL UNIQUE
);

CREATE TABLE courses (
  id INTEGER PRIMARY KEY,
  title TEXT NOT NULL,
  department_id INTEGER NOT NULL,
  FOREIGN KEY (department_id) REFERENCES departments(id)
);

INSERT INTO departments (id, name) VALUES
  (1, 'Engineering'),
  (2, 'Design');

INSERT INTO courses (id, title, department_id) VALUES
  (101, 'SQL Basics', 1),
  (102, 'Data Modeling', 1),
  (103, 'UX Foundations', 2);

SELECT courses.title, departments.name AS department
FROM courses
JOIN departments
  ON departments.id = courses.department_id
ORDER BY courses.id;
QUERY OUTPUT
Edit the query, predict the rows it will return, then run it.

Each run starts a fresh SQLite database in an isolated browser worker. Your edited SQL is saved on this device, but the database and its rows are discarded after the run.

Try this next: Add a fourth course for department 1 and predict where it appears in the ordered result.

Primary key

Answers “which exact row?” inside one table and provides a stable target for references.

Foreign key

Answers “which related row?” and can reject references that would otherwise become orphaned.

Join condition

Explains how matching keys reconstruct a result from normalized tables without permanently merging them.

A query result is a shaped view, not a second copy of the table

The table retains all four columns in this example, but the query returns only title and pages for finished books. WHERE chooses qualifying rows, the select list chooses output columns, and ORDER BY controls presentation. The query does not delete the unfinished row or remove columns from the stored table.

SQL BROWSER RUNNER

Shape a focused result set

Run the query, then change finished = 1 to a pages condition. Try pages >= 300 and predict the new order.

CREATE TABLE books (
  id INTEGER PRIMARY KEY,
  title TEXT NOT NULL,
  pages INTEGER NOT NULL CHECK (pages > 0),
  finished INTEGER NOT NULL CHECK (finished IN (0, 1))
);

INSERT INTO books (id, title, pages, finished) VALUES
  (1, 'Database Design', 280, 1),
  (2, 'Reliable Queries', 360, 0),
  (3, 'Data Systems', 420, 1);

SELECT title, pages
FROM books
WHERE finished = 1
ORDER BY pages DESC;
QUERY OUTPUT
Edit the query, predict the rows it will return, then run it.

Each run starts a fresh SQLite database in an isolated browser worker. Your edited SQL is saved on this device, but the database and its rows are discarded after the run.

Try this next: Return every book with at least 300 pages and order equal page counts alphabetically by title.

Read a query as a question

“From the books table, keep finished rows, return title and pages, and show the longest first.” Translating syntax into a precise sentence exposes vague requirements before they become incorrect queries.

Constraints move essential rules closer to the data

NOT NULL requires a value. UNIQUE prevents two rows from using the same candidate value. CHECK tests a row-level condition. PRIMARY KEY combines identity and uniqueness rules. FOREIGN KEY protects references between tables. These constraints do not replace application validation; they provide a final shared boundary for every application, script, import, and administrator that writes to the database.

A rule belongs in the schema when invalid data would be invalid regardless of which interface produced it. A book with negative pages is not merely a form error—it contradicts the model. A message about how to help a user repair the field belongs in the application, but the database should still reject the impossible record.

Know what the runnable SQL environment does

SovranCode’s SQL runner loads SQLite compiled to WebAssembly and executes each block in a Web Worker. It does not receive database credentials, production access, server filesystem access, or access to an existing database. This is ideal for syntax, data modeling, and deterministic practice. It is not a substitute for verifying PostgreSQL- or MySQL-specific behavior in that engine.

  • Every example creates the schema and data it needs, so a run does not depend on an earlier block.
  • Each database is in memory and is discarded after the block finishes.
  • The output shows result columns and rows, or a clear completion or error message.
  • Production credentials and protected data never belong in a learning notebook.

Independent lab: model teams and developers

Use the starter as a working system, then make it your own. Add one team and two developers. Keep every team_id valid. Change the result so it includes the developer identifier, developer name, and team name. Finally, order first by team and then by developer.

SQL BROWSER RUNNER

Build and query a two-table model

Do not stop when it runs. Explain what one row means in each table and why the join condition uses two different columns with the same values.

PRAGMA foreign_keys = ON;

CREATE TABLE teams (
  id INTEGER PRIMARY KEY,
  name TEXT NOT NULL UNIQUE
);

CREATE TABLE developers (
  id INTEGER PRIMARY KEY,
  name TEXT NOT NULL,
  team_id INTEGER NOT NULL,
  FOREIGN KEY (team_id) REFERENCES teams(id)
);

INSERT INTO teams (id, name) VALUES
  (1, 'Platform'),
  (2, 'Learning');

INSERT INTO developers (id, name, team_id) VALUES
  (101, 'Mina', 2),
  (102, 'Omar', 1),
  (103, 'Nora', 2);

SELECT developers.name, teams.name AS team
FROM developers
JOIN teams ON teams.id = developers.team_id
ORDER BY teams.name, developers.name;
QUERY OUTPUT
Edit the query, predict the rows it will return, then run it.

Each run starts a fresh SQLite database in an isolated browser worker. Your edited SQL is saved on this device, but the database and its rows are discarded after the run.

Try this next: Add one team and two developers, include every requested output column, and verify the final sort order.

Lab review criteria

Your result should contain five developers after your additions, every developer should reference an existing team, the team name should not be copied into the developers table, and the final SELECT should produce a readable, explicitly ordered report.

Common beginner mistakes—and the better question

“The table order changed.”

Was an ORDER BY requested?

Storage order and result order are not a contract. Ask for the exact order needed by the consumer.

“The name can identify the row.”

Can that name change?

Prefer a stable key for identity, then place uniqueness rules on business values that truly require them.

“The app validates it.”

Can any other writer bypass the app?

Keep essential integrity in the schema so imports, scripts, and future applications obey it too.

“SQL is SQL everywhere.”

Which DBMS will run this?

Separate transferable relational reasoning from engine-specific functions, types, and operational behavior.

Lesson review

You now have the foundation that later statements depend on. A database contains organized structures and data; a DBMS manages them; SQL describes definitions, changes, and results. Tables model one kind of fact, rows represent occurrences, columns represent attributes, keys create identity and relationships, constraints protect shared truths, and queries construct focused result sets without rewriting the stored tables.

  • I can distinguish the database, DBMS, and SQL language using a concrete example.
  • I can state what one row means in each table before choosing its columns.
  • I can explain schema versus current data and identify a primary-key and foreign-key contract.
  • I can run a complete create–insert–select example and translate the final query into a precise sentence.
  • I know that SQL results require explicit ordering and that engine-specific behavior must be verified.
KNOWLEDGE CHECK

Check the relational mental model

Answer every question before checking. Read every explanation—even a correct choice can hide a weak reason.

01Which statement best separates a database, a DBMS, and SQL?
02What does one row in a well-designed courses table normally represent?
03Why should a primary key be stable and unique?
04What is the main purpose of a foreign key?
05What does SELECT describe?
06Why does a lesson runner create a new in-memory database for each code block?
07Which claim about SQL portability is most accurate?
COURSE OVERVIEWSQL: Query, Model, and Analyze Data
NEXT LESSONTables, Rows, Columns, and Schemas
ON THIS PAGEDatabases, SQL, and the Relational ModelLesson mapDatabase, DBMS, and SQLRelational modelFirst databaseSchema and dataKeys and relationshipsQuery resultsIntegrity constraintsSafe runnerIndependent labCommon mistakesLesson reviewKnowledge check
Course contents