Document the features the main merge shipped: `create m:n relationship` (relationships ref + build-the-library note), the `--demo` teaching flag (command-line-options), the Ctrl-O schema sidebar (output-pane, now .mdx to embed the new cast), and horizontal/two-row input (assistive-editor).
8.1 KiB
title, description, sidebar
| title | description | sidebar | ||
|---|---|---|---|---|
| Build the library | Build the whole example library — four tables, a one-to-many and a many-to-many relationship, and some rows — step by step. |
|
This guide builds the 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 leaves off. The only new idea is relationships, which we introduce as we go.
:::tip Type each command into the input field and press Enter. As you type, the editor completes commands with Tab and flags mistakes before you run them — see 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:
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:
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 the database will enforce on every insert:
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):
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
for the other options.
3. Create the members table
Members are the people who borrow books. This table stands alone for now:
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.
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:
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.
:::
You can confirm all three relationships at once:
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:
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:
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:
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:
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:
show data authors
┌───────────┬───────────────────┬────────────┐
│ author_id │ name │ birth_year │
├───────────┼───────────────────┼────────────┤
│ 1 │ Ursula K. Le Guin │ 1929 │
│ 2 │ Italo Calvino │ 1923 │
│ 3 │ Octavia E. Butler │ 1947 │
└───────────┴───────────────────┴────────────┘
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
loansbridge only really pays off when you query through it. See Querying with joins. - See the relationships drawn out —
show table booksandshow relationship books_authorrender the links as diagrams (Relationships). - Try the same build in advanced mode to see the SQL form of each command (Querying & inspecting, Tables).