Skip to content
academia.sh

Lesson 01 / 18

SQL Language Families

Definition, manipulation, querying, control, and transaction statements: what each family changes, what declarative syntax means, and setting up the library schema used throughout the course.

Contents

The Data Modeling and Relational Theory course closed by leaving behind a schema: relations, primary and foreign keys, entity and referential integrity constraints, normalized tables. What that course produced was a design — consistent on paper, but not yet questioned. A schema’s value is measured by the questions that can be asked of it.

This course builds the language that asks those questions. The language is called Structured Query Language (SQL), the standard interface that puts the relational model’s theoretical operations — selection, projection, join — into writing. The first lesson maps the language: which statement family changes what, how a statement is read, and how the data used throughout the course gets set up.

A Declarative Language

Every loop written in the Programming Fundamentals course answered the question of how: walk the array from start to end, add the ones that satisfy the condition to an accumulator, return the result. SQL does not ask that question. SQL writes what is wanted; the engine decides in which order, with which data structure, and through which index the result gets reached. This is why SQL is a declarative language.

The practical consequence of the distinction is this: two queries that express the same question with different syntax run at the same speed when the query plan the engine picks is the same. The syntax itself does not determine performance; what determines it is the plan the engine derives from the syntax. This distinction returns later in the course — for now it is enough to know that improving a query in SQL is mostly not about speeding up a loop, but about asking the question more precisely.

Statement Families

SQL is taught as a single language, but it holds five statement sets inside it that do five different jobs. These sets are conventionally named as follows:

Family Expansion What it does Example statements
Definition data definition language Builds and changes the schema itself CREATE, ALTER, DROP
Manipulation data manipulation language Inserts, changes, deletes rows in tables INSERT, UPDATE, DELETE
Querying data query language Produces a new result set from existing data SELECT
Control data control language Grants and revokes privileges on objects GRANT, REVOKE
Transaction transaction control language Commits or rolls back a group of changes as a whole COMMIT, ROLLBACK

The distinction is not arbitrary: each family differs in what it affects and in whether it can be rolled back. Querying changes nothing. Manipulation changes rows, and it can be rolled back if it sits inside a transaction. Definition changes the schema, and whether that can be rolled back depends on the engine — some engines treat a schema change as part of the transaction, others commit the open transaction the moment they see a definition statement.

This course’s first two topics deal only with querying; the third topic moves on to manipulation and definition statements. Control statements are also covered in that topic.

Building the Schema

One example runs throughout the course: a library’s loan records. There are four tables — branches, books, members, and loan transactions. This is the same schema that was normalized in the Data Modeling and Relational Theory course.

The block below creates a database file and defines the four tables. The engine invoked on the command line is sqlite3; the file name is library.db. The statements themselves are standard definition statements.

rm -f library.db
sqlite3 library.db <<'SQL'
CREATE TABLE branch (
  branch_id INTEGER PRIMARY KEY,
  name      TEXT NOT NULL,
  city      TEXT NOT NULL
);
CREATE TABLE book (
  book_id           INTEGER PRIMARY KEY,
  title             TEXT NOT NULL,
  author            TEXT NOT NULL,
  publication_year  INTEGER,
  branch_id         INTEGER REFERENCES branch(branch_id)
);
CREATE TABLE member (
  member_id     INTEGER PRIMARY KEY,
  first_name    TEXT NOT NULL,
  last_name     TEXT NOT NULL,
  email         TEXT,
  registered_at TEXT NOT NULL
);
CREATE TABLE loan (
  loan_id      INTEGER PRIMARY KEY,
  book_id      INTEGER NOT NULL REFERENCES book(book_id),
  member_id    INTEGER NOT NULL REFERENCES member(member_id),
  pickup_date  TEXT NOT NULL,
  return_date  TEXT
);
SQL
sqlite3 library.db '.tables'
book    branch  loan    member

Three concepts from the Data Modeling and Relational Theory course appear directly in the definitions. PRIMARY KEY states the primary key, REFERENCES the foreign key, and NOT NULL states that a column does not accept a null value. The absence of NOT NULL on the publication_year, email, and return_date columns is deliberate: a book can have an unknown publication year, a member can have given no email address, and a loan record can not yet have been returned. These three columns will be used later in the course to show how null values behave.

Loading the Data

A schema is an empty skeleton. The block below inserts sample rows into the library.db file created in the previous block and prints the row count per table. The .headers on and .mode column lines set the command-line tool’s output format; they have nothing to do with the query itself.

sqlite3 library.db <<'SQL'
INSERT INTO branch VALUES (1,'Central','Ankara'),(2,'Bahcelievler','Ankara'),
  (3,'Kadikoy','Istanbul'),(4,'Konak','Izmir');
INSERT INTO book VALUES (1,'Blindness','José Saramago',1995,1),(2,'The Disconnected','Oğuz Atay',1972,1),
  (3,'The Book of Sand','Jorge Luis Borges',1975,2),(4,'Yaban','Yakup Kadri',1932,2),
  (5,'Silent House','Orhan Pamuk',1983,3),(6,'Motherland Hotel','Yusuf Atılgan',NULL,3),
  (7,'Tehlikeli Oyunlar','Oğuz Atay',1973,NULL);
INSERT INTO member VALUES (1,'Alice','Kane','[email protected]','2023-02-14'),
  (2,'Ben','Ortiz','[email protected]','2023-05-30'),(3,'Clara','Diaz',NULL,'2024-01-09'),
  (4,'Derek','Voss','[email protected]','2024-03-22'),(5,'Grace','Kim',NULL,'2024-11-05'),
  (6,'Owen','Park','[email protected]','2025-01-18');
INSERT INTO loan VALUES (1,1,1,'2025-01-10','2025-01-24'),(2,2,1,'2025-02-02','2025-02-20'),
  (3,1,2,'2025-02-11',NULL),(4,3,3,'2025-03-01','2025-03-15'),(5,4,3,'2025-03-18','2025-04-02'),
  (6,1,4,'2025-04-05','2025-04-19'),(7,5,4,'2025-04-21',NULL),(8,2,5,'2025-05-02','2025-05-30'),
  (9,7,1,'2025-05-14','2025-05-28'),(10,3,5,'2025-06-03',NULL),(11,6,2,'2025-06-11','2025-06-25'),
  (12,4,4,'2025-06-20','2025-07-04');
.headers on
.mode column
SELECT 'book' AS table_name, COUNT(*) AS rows FROM book
UNION ALL SELECT 'member', COUNT(*) FROM member
UNION ALL SELECT 'loan', COUNT(*) FROM loan;
SQL
table_name  rows
----------  ----
book        7   
member      6   
loan        12  

These two blocks will repeat throughout the course. So that each lesson can run on its own, the same schema and data will be given again at the start of the following lessons, compressed into a single block.

The Skeleton of a Query

The third family — querying — consists of a single statement: SELECT. The shortest question directed at the data just set up looks like this.

sqlite3 library.db <<'SQL'
.headers on
.mode column
SELECT title, publication_year FROM book WHERE author = 'Oğuz Atay';
SQL
title              publication_year
-----------------  ----------------
The Disconnected   1972            
Tehlikeli Oyunlar  1973            

The statement consists of three clauses: SELECT states which columns come back, FROM states which table gets read, and WHERE states which rows stay. That is the order they are written in, but the order they are evaluated in is different — the engine evaluates FROM first, then WHERE, and SELECT last. The next lesson works out this order in detail.

Three syntax rules already apply. Keywords are not case-sensitive; writing them in uppercase is only a readability convention. Text values are enclosed in single quotes — in the standard, double quotes are for quoting an identifier, meaning a table or column name. Every statement ends with a semicolon; this is what lets multiple statements be written one after another.

The Reversibility of a Transaction

Manipulation statements change rows, not the schema, and this change can be held temporarily inside a transaction. A transaction is a block of statements that either commits as a whole or rolls back as a whole.

sqlite3 library.db <<'SQL'
.headers on
.mode column
BEGIN;
DELETE FROM loan WHERE return_date IS NULL;
SELECT COUNT(*) AS in_transaction FROM loan;
ROLLBACK;
SELECT COUNT(*) AS after_rollback FROM loan;
SQL
in_transaction
--------------
9             
after_rollback
--------------
12            

Inside the transaction, the table appears to have nine rows; after the rollback, twelve again. The three deleted rows never became permanent. Had COMMIT been written, the result would have settled at nine rows. Transaction isolation levels and concurrency behavior are the subject of the Advanced SQL course; here only this much is needed: the safe way to try out a change is to put it inside a block that starts with BEGIN.

Standard and Dialect

SQL rests on a standard, but no engine implements the standard in full, and every engine adds its own extensions on top of the standard. These extensions are called a dialect. The rules taught in the course belong to the standard; where a behavior depends on the engine, the text marks it explicitly.

In practice the distinction shows up in three places. The first is the syntax for limiting a result set — the standard syntax and the common shortcut differ. The second is the case-sensitivity behavior of pattern matching. The third is that some aspects of the outer join are not present in every engine. All three are taken up separately in their own lessons.

The stance to take toward dialect differences is to treat portability as a measure, not a goal: choosing dialect-specific syntax when standard syntax is available ties the query to a particular product. This is sometimes a deliberate decision; when it is not, it comes back later as a migration cost.

Summary

  • SQL is a declarative language: what the result will be gets written, and the engine decides how to compute it.
  • Statements fall into five families — definition, manipulation, querying, control, and transaction — and each family differs in what it affects and in whether it can be rolled back.
  • The schema used throughout the course consists of four tables: branch, book, member, and loan; three columns that accept null values were left deliberately.
  • A query is built from clauses, and the order they are written in is not the order they are evaluated in.
  • Manipulation statements can be tried out inside a transaction; ROLLBACK makes the change as if it never happened.
  • Standard SQL and an engine’s dialect are separate things; engine-dependent behavior is marked separately throughout the course.

Next Step

In this lesson, SELECT appeared only as an example. Yet the entire querying family consists of this single statement, and its power comes from the column list accepting far more than fixed names: computed expressions, renamed columns, the elimination of duplicate rows. The next lesson builds the structure of the SELECT clause and the difference between a table’s columns and a query’s columns.

To keep your progress and take notes, Log in

My notes

Log in to take notes.

Start typing to search.

↑↓ Esc navigate · open · close