CREATE TABLE CourseContents (
CourseContentsId INTEGER NOT NULL PRIMARY KEY,
CourseContentType CHAR(1) CHECK (CourseContentType IN ('T', 'Q')),
CourseId INTEGER REFERENCES Courses(Id),
SNo INTEGER NOT NULL,
CONSTRAINT UniqueCourseContent UNIQUE (CourseId, SNo),
CONSTRAINT UniqueCourseContentMapping UNIQUE (CourseContentsId, CourseContentType),
);
Таблица содержания курса генерирует уникальный идентификатор (CourseContentsId) для каждой комбинации CourseId и SNo, на который затем можно ссылаться в таблице «Темы и тесты».Поскольку существуют две разные таблицы (темы и тесты), мы вводим еще один столбец, в котором указывается тип контента (тема / тест), с которым он связан.Используя составное ограничение UNIQUE для CourseContentsId & CourseContentType, мы гарантируем, что каждая запись может быть связана только с одним типом контента.
CREATE TABLE CourseTopics (
CourseContentsId INTEGER NOT NULL,
CourseContentType CHAR(1) DEFAULT 'T' CHECK (CourseContentType = 'T'),
TopicId INTEGER REFERENCES Topics(Id),
PRIMARY KEY (CourseContentsId, CourseContentType),
FOREIGN KEY (CourseContentsId, CourseContentType) REFERENCES CourseContents (CourseContentsId, CourseContentType)
);
Таблица тем курса - это таблица отображения между темами и курсами (у нас есть много-много отношения между таблицами курсов и тем).Внешний и первичный ключ к таблице CourseContents гарантирует, что у нас будет одна запись для каждого CourseContent (другими словами, Course & SNo).Таблица ограничивает CourseContentType только тем, чтобы принимать 'T', что означает, что данный CourseContentId должен иметь тип содержимого Темы, чтобы быть связанным с Темой.
CREATE TABLE CourseQuizzes (
CourseContentsId INTEGER NOT NULL,
CourseContentType CHAR(1) DEFAULT 'Q' CHECK (CourseContentType = 'Q'),
QuizId INTEGER REFERENCES Quizzes(Id),
PRIMARY KEY (CourseContentsId, CourseContentType),
FOREIGN KEY (CourseContentsId, CourseContentType) REFERENCES CourseContents (CourseContentsId, CourseContentType)
);
По аналогии с таблицей Тем мы теперь создаем таблицу CourseQuizzes.Единственное отличие состоит в том, что у нас есть CourseContentType 'Q'.
Наконец, чтобы упростить запросы, мы можем создать представление, объединяющее эти таблицы.Например, в представлении ниже будут перечислены: CourseId, SNo, ContentType, TopicId, QuizId.В контексте книги, с помощью этого представления вы можете получить то, что находится на определенном номере страницы (SNo) данной книги (курса), с типом содержимого на странице (тема или викторина) и идентификатором содержимого.
CREATE VIEW CourseContents_All AS
SELECT CourseContents.CourseId, CourseContents.SNo, CourseContents.CourseContentType , CourseTopics.Id, CourseQuizzes.Id
FROM CourseContents
LEFT JOIN CourseTopics ON (CourseContents.CourseContentsId = CourseTopics.CourseContentsId)
LEFT JOIN CourseQuizzes ON (CourseContents.CourseContentsId = CourseQuizzes.CourseContentsId);
Преимущества, которые я чувствую при таком подходе:
- Эта структура следует за наследованием, что означает, что мы можем поддерживать больше типов контента, просто добавив другую таблицу и изменив CourseContentType Проверить ограничение вТаблица CourseContents.
- Для заданного идентификатора курса и номера SNo.я также знаю тип контента.Это, безусловно, поможет в коде приложения.
Примечание. Проверочное ограничение не работает в MySQL.Для этого нужно использовать триггеры.