Ситуация: разработать простую базу данных для коллекции книг.
Сущности:
1. Book table;
2. Author table;
3. Publisher table
4. Imprints table (possibly).
Наблюдения:
1. Books must contain two foreign keys;
1. Author_ID
2. Publisher_ID or Imprint_ID
Проблемы, которые необходимо решить:
1. Publishers have Imprints;
2. Books bear the Imprint name though the Imprint belongs to a Publisher.
3. How do we handle this issue?;
Поскольку в книге выходные данные указаны в качестве издателя, кажется логичным, что выходные данные должны быть в таблице издателей. Однако связь «Издатель — выходные данные» — это связь «один ко многим». Итак, есть два вопроса:
Я попытался использовать атрибут в таблице «Книги», чтобы указать, к какой таблице обращаться. Это не удовлетворило человека, для которого я разрабатываю базу данных.
«Поскольку в книге в качестве издателя указан издательский дом», <-- Ошибка номер 1.
У книг может быть более одного автора. А у некоторых книг помимо авторов или вместо них есть иллюстраторы или редакторы.


У издателей есть выходные данные
Это требование дает вам два варианта:
Book должен ссылаться на Imprint, а Imprint ссылается на своего родителя Publisher.
Books.ImprintId ➤ Imprints.ImprintId и Imprints.PublisherId ➤ Publishers.PublisherId.Book должен ссылаться на свой Publisher и свой Imprint.
Books.ImprintId ➤ Imprints.ImprintId и Books.PublisherId ➤ Publishers.PublisherId и Imprints.PublisherId ➤ Publishers.PublisherId, так что Book также невозможно ссылаться на Imprint, который не принадлежит тому же самому Publisher.Учитывая, что не у всех издателей есть выходные данные, а также поскольку я поклонник составных ключей и хочу донести до всех информацию о существовании составных ключей, я предлагаю последнее решение, например:
(Кстати, я использую ISO SQL, а не MySQL, so you can't just copy-and-paste this into your homework)
CREATE TABLE Publishers (
PublisherId int NOT NULL GENERATED ALWAYS AS IDENTITY,
Name varchar(50) NOT NULL,
CONSTRAINT PK_Publishers PRIMARY KEY ( PublisherId )
);
CREATE TABLE Imprints (
PublisherId int NOT NULL,
ImprintId int NOT NULL GENERATED ALWAYS AS IDENTITY,
Name varchar(50) NOT NULL,
CONSTRAINT PK_Imprints PRIMARY KEY ( ImprintId, PublisherId ) /* This is a composite PK */
CONSTRAINT FK_Imprints_to_Publishers FOREIGN KEY ( PublisherId ) REFERENCES Publishers ( PublisherId )
);
CREATE TABLE Books (
PublisherId int NOT NULL,
ImprintId int NULL, /* This is NULLable to accomodate the case when a book has a publisher, but no imprint. */
BookId int NOT NULL GENERATED ALWAYS AS IDENTITY,
Title varchar(50) NOT NULL,
AuthorId int NOT NULL, /* etc */
CONSTRAINT PK_Books PRIMARY KEY ( BookId ) /* It's up to you if you want Books to have a composite PK or not. */
CONSTRAINT FK_Books_to_Publishers FOREIGN KEY ( PublisherId ) REFERENCES Publishers ( PublisherId ),
CONSTRAINT FK_Books_to_Imprints FOREIGN KEY ( ImprintId, PublisherId ) REFERENCES Imprints ( ImprintId, PublisherId ) /* The composite FK here makes it impossible to reference an Imprint that doesn't belong to the correct Publisher */
CONSTRAINT FK_Books_to_Authors FOREIGN KEY ( AuthorId ) REFERENCES Authors ( AuthorId ) /* etc */
);
CREATE TABLE Authors (
/* an exercise left for the reader */
);
Книги имеют название Выходные данные, хотя Выходные данные принадлежат Издателю.
В вашем TABLE Book на самом деле не будет столбца, содержащего ImprintName, потому что это будет денормализацией, а весь смысл использования СУБД состоит в том, чтобы иметь нормализованное хранилище данных - поэтому вместо этого я предполагаю, что вы имеете в виду, что ваши запросы OLAP (отчетность, анализ) о Книги должны содержать название выходных данных, и это нормально:
SELECT
b.Title AS BookTitle,
a.Name AS AuthorName,
p.Name AS PublisherName,
i.Name AS ImprintName
FROM
Books AS b
INNER JOIN Authors AS a ON a.AuthorId = b.AuthorId
INNER JOIN Publishers AS p ON p.PublisherId = b.PublisherId
LEFT OUTER JOIN Imprints AS i ON i.PublisherId = b.PublisherId AND i.ImprintId = b.ImprintId;
(В Books ➤ Imprints используется LEFT OUTER JOIN вместо INNER JOIN для размещения книг с издателями, но без выходных данных).
Если Издатель и Выходные данные — это отдельные таблицы. как нам узнать, к какой таблице нужно получить доступ, чтобы получить издателя, указанного в книге?
См. выше.
«Это не устроило человека, для которого я разрабатываю базу данных». - то есть курс ТА вашей базы данных?