---
title: Build the library
description: Build the whole example library — four tables, a one-to-many and a many-to-many relationship, and some rows — step by step.
sidebar:
  order: 1
---

This guide builds the [example library](/getting-started/example-library/)
from scratch in **simple mode**. By the end you will have a complete little
database — `authors`, `books`, `members`, and `loans` — wired together with
both kinds of relationship, and you will have used the whole
**create → add columns → relate → insert → query** loop.

It picks up where [Your first project](/getting-started/first-project/) leaves
off. The only new idea is *relationships*, which we introduce as we go.

:::tip
Type each command into the input field and press <kbd>Enter</kbd>. As you
type, the editor completes commands with <kbd>Tab</kbd> and flags mistakes
before you run them — see
[The assistive editor](/using-the-playground/the-assistive-editor/).
:::

## 1. Create the authors table

We give each table a **named** primary key (like `author_id`) so that
relationships read clearly later. `with pk author_id(serial)` makes the key a
`serial` — an auto-incrementing number the database fills in for you:

```rdbms
create table authors with pk author_id(serial)
add column to authors: name (text)
add column to authors: birth_year (int)
```

## 2. Create the books table and relate it to authors

Build `books` the same way. The `author_id` column will hold *which* author
wrote each book:

```rdbms
create table books with pk book_id(serial)
add column to books: title (text)
add column to books: author_id (int)
add column to books: published (int)
add column to books: isbn (text)
```

No two books should share an ISBN, so mark that column unique — a
[constraint](/reference/constraints/) the database will enforce on every
insert:

```rdbms
add constraint unique to books.isbn
```

Now the new idea. Every book is written by one author, but an author can write
many books — a **one-to-many** relationship. We declare it so the database
keeps the link honest (you can never point a book at an author who does not
exist):

```rdbms
add 1:n relationship as books_author from authors.author_id to books.author_id on delete cascade
```

Read it parent-to-child: **from** the `authors` side (the "one") **to** the
`books` side (the "many"). `on delete cascade` says that if an author is ever
deleted, their books go too — see [Relationships](/reference/relationships/)
for the other options.

## 3. Create the members table

Members are the people who borrow books. This table stands alone for now:

```rdbms
create table members with pk member_id(serial)
add column to members: name (text)
add column to members: joined (date)
```

## 4. Create the loans table — the many-to-many bridge

A book can be borrowed by many members over time, and a member can borrow many
books. That is a **many-to-many** relationship, and you do not model it with a
single link — you use a third table in the middle. Each row in `loans`
represents *one borrowing event*: one book, one member, and when it happened.

```rdbms
create table loans with pk loan_id(serial)
add column to loans: book_id (int)
add column to loans: member_id (int)
add column to loans: loaned_on (date)
add column to loans: returned_on (date)
```

`loans` is a **bridge table** (also called a junction table). It carries two
one-to-many relationships — one to `books`, one to `members` — and together
they express the many-to-many link:

```rdbms
add 1:n relationship as loans_book from books.book_id to loans.book_id on delete cascade
add 1:n relationship as loans_member from members.member_id to loans.member_id on delete cascade
```

:::note
We build the bridge by hand here because `loans` carries its own columns
(`loaned_on`, `returned_on`) — it records *when* each borrowing happened, not
just *that* it did. For a pure link with no extra columns, the
`create m:n relationship` command builds the junction table and both
relationships in one step — see
[Many-to-many relationships](/reference/relationships/#many-to-many-relationships).
:::

You can confirm all three relationships at once:

```rdbms
show relationships
```

```
Relationships (3):
  books_author: authors.author_id → books.author_id on delete cascade
  loans_book: books.book_id → loans.book_id on delete cascade
  loans_member: members.member_id → loans.member_id on delete cascade
```

## 5. Add some rows

The `serial` keys (`author_id`, `book_id`, …) fill themselves in, so you leave
them out of each `insert`. Start with the authors:

```rdbms
insert into authors (name, birth_year) values ('Ursula K. Le Guin', 1929)
insert into authors (name, birth_year) values ('Italo Calvino', 1923)
insert into authors (name, birth_year) values ('Octavia E. Butler', 1947)
```

Then their books. The `author_id` values (`1`, `2`, `3`) are the keys the
database just assigned above — Le Guin is `1`, Calvino is `2`, Butler is `3`:

```rdbms
insert into books (title, author_id, published, isbn) values ('A Wizard of Earthsea', 1, 1968, '978-0553383041')
insert into books (title, author_id, published, isbn) values ('The Left Hand of Darkness', 1, 1969, '978-0441478125')
insert into books (title, author_id, published, isbn) values ('Invisible Cities', 2, 1972, '978-0156453806')
insert into books (title, author_id, published, isbn) values ('Kindred', 3, 1979, '978-0807083697')
```

A couple of members:

```rdbms
insert into members (name, joined) values ('Grace Hopper', '2023-01-15')
insert into members (name, joined) values ('Alan Turing', '2023-03-02')
```

And finally two loans, linking a book to a member. Grace Hopper has borrowed
book `1` and not yet returned it; Alan Turing borrowed book `3` and returned
it. Leave `returned_on` out when the book is still on loan:

```rdbms
insert into loans (book_id, member_id, loaned_on) values (1, 1, '2024-05-01')
insert into loans (book_id, member_id, loaned_on, returned_on) values (3, 2, '2024-05-03', '2024-05-20')
```

## 6. Look at your data

Every table now has rows. `show data` prints them:

```rdbms
show data authors
```

```
┌───────────┬───────────────────┬────────────┐
│ author_id │ name              │ birth_year │
├───────────┼───────────────────┼────────────┤
│         1 │ Ursula K. Le Guin │       1929 │
│         2 │ Italo Calvino     │       1923 │
│         3 │ Octavia E. Butler │       1947 │
└───────────┴───────────────────┴────────────┘
```

```rdbms
show data loans
```

```
┌─────────┬─────────┬───────────┬────────────┬─────────────┐
│ loan_id │ book_id │ member_id │ loaned_on  │ returned_on │
├─────────┼─────────┼───────────┼────────────┼─────────────┤
│       1 │       1 │         1 │ 2024-05-01 │ (null)      │
│       2 │       3 │         2 │ 2024-05-03 │ 2024-05-20  │
└─────────┴─────────┴───────────┴────────────┴─────────────┘
```

The empty `returned_on` shows as `(null)` — the loan that is still out.

## Where to go next

You now have the complete library. From here:

- **Ask questions across tables** — the `loans` bridge only really pays off
  when you query through it. See
  [Querying with joins](/guides/querying-with-joins/).
- **See the relationships drawn out** — `show table books` and
  `show relationship books_author` render the links as diagrams
  ([Relationships](/reference/relationships/)).
- **Try the same build in advanced mode** to see the SQL form of each command
  ([Querying & inspecting](/reference/querying-and-inspecting/),
  [Tables](/reference/tables/)).
