ErdDocs

Примеры / Библиотечная система

Библиотечная система

Схема библиотеки держится на одном разделении. Книга – это название в каталоге, а экземпляр – физический том на полке. Читатели берут экземпляры, а не книги, а бронь ставится на книгу. Авторы подключаются через промежуточную таблицу, потому что у книги бывает несколько авторов.

Ниже ErdDocs рисует эту схему по её SQL, со всеми таблицами и связями. На вкладке «Словарь данных» – справочник для печати, целиком и бесплатно на этой странице. SQL ещё ниже.

Ваша схема

Наведите на таблицу, чтобы подсветить её связи, кликните, чтобы закрепить.

Зачем нужна каждая таблица

  • books / copiesЗапись каталога и экземпляр со штрихкодом. Большинство задач про библиотеку сводятся к этому разделению.
  • authors / book_authorsМногие ко многим: книга с двумя авторами сразу ломает прямой author_id.
  • membersЛюди пользуются номером читательского билета, card_no.
  • loansВыдача привязана к экземпляру, потому что нужно знать, какой именно том на руках и просрочен.
  • reservationsБронь привязана к книге. Читателю нужно название, и неважно, какой экземпляр вернётся первым.

Проектные решения, которые стоит взять

  • Выдачи ссылаются на экземпляры, брони – на книги. Смешать эти два уровня – классическая ошибка. Тогда схема не ответит ни на вопрос «у кого этот том», ни на вопрос «кого уведомить следующим».
  • returned_on допускает NULL. Это заменяет флаг «возвращён», а дата хранится в той же колонке.
  • ISBN уникален, но допускает NULL. Старые и внутренние издания без ISBN существуют, и с NOT NULL реальные данные нарушали бы ограничение.

SQL

Диалект PostgreSQL. Этот SQL уже вставлен в инструмент выше, его можно перенести в свою базу или в миграцию и свободно копировать.

CREATE TABLE authors (
    id         bigserial    PRIMARY KEY,
    full_name  varchar(120) NOT NULL
);

CREATE TABLE books (
    id        bigserial    PRIMARY KEY,
    isbn      varchar(17)  UNIQUE,
    title     varchar(240) NOT NULL,
    published smallint
);
COMMENT ON COLUMN books.isbn IS 'NULL для изданий до ISBN и внутренних материалов';

CREATE TABLE book_authors (
    book_id    bigint NOT NULL REFERENCES books(id),
    author_id  bigint NOT NULL REFERENCES authors(id),
    PRIMARY KEY (book_id, author_id)
);

CREATE TABLE copies (
    id        bigserial   PRIMARY KEY,
    book_id   bigint      NOT NULL REFERENCES books(id),
    barcode   varchar(20) NOT NULL UNIQUE,
    shelf     varchar(20),
    condition varchar(20) NOT NULL DEFAULT 'good'
);
COMMENT ON TABLE copies IS 'Физический том; у популярной книги много экземпляров';

CREATE TABLE members (
    id         bigserial    PRIMARY KEY,
    card_no    varchar(20)  NOT NULL UNIQUE,
    full_name  varchar(120) NOT NULL,
    joined_on  date         NOT NULL
);

CREATE TABLE loans (
    id          bigserial PRIMARY KEY,
    copy_id     bigint    NOT NULL REFERENCES copies(id),
    member_id   bigint    NOT NULL REFERENCES members(id),
    loaned_on   date      NOT NULL,
    due_on      date      NOT NULL,
    returned_on date
);
COMMENT ON COLUMN loans.returned_on IS 'NULL, пока экземпляр на руках';

CREATE TABLE reservations (
    id          bigserial   PRIMARY KEY,
    book_id     bigint      NOT NULL REFERENCES books(id),
    member_id   bigint      NOT NULL REFERENCES members(id),
    placed_at   timestamptz NOT NULL DEFAULT now(),
    fulfilled   boolean     NOT NULL DEFAULT false
);
COMMENT ON TABLE reservations IS 'Бронь на КНИГУ: её закроет любой вернувшийся экземпляр';

Частые вопросы

Куда положить штрафы?

В таблицу fines со ссылкой на loans, ведь штраф берут за просроченную выдачу. В ней сумма, дата начисления и дата оплаты. Для учебного проекта подойдёт и расчёт на лету по сроку возврата. Главное – объяснить выбор.

Как изменится схема с электронными книгами?

У электронной книги нет экземпляров, и выдача становится вопросом лицензий. Можно завести таблицу licenses рядом с copies, где указано число одновременных выдач. А можно выдавать прямо книгу и проверять число выдач в приложении.

Другие примеры