Реферирование данных из нескольких таблиц

голоса
-2

У меня есть три простых объектов:

Курс, как книга, проданный в состоянии продукт. Субъект курс представляет собой курс и имеет различные свойства, такие как продолжительность, пошлины, автор, тип и так далее.

Course 
{
    int Id;
    string Title;
}

Тема, подобно отдельная страница в книге, он имеет реальное содержание обучения. Тема, может появиться в нескольких курсов.

Topic
{
    int Id;
    string Title;
}

В контексте книги, викторины также отдельная страница, которая содержит вопросы вместо содержания обучения. Опять викторина может быть появиться на несколько курсов.

Quiz
{
    int Id;
    string Title;
}

Теперь, когда у меня есть отдельные темы и викторины я хочу иметь таблицу, которая будет собираться Темы и викторины в книге. Рассмотрим эту таблицу в качестве оглавления в книге. Ниже приводится изложение того, что я жду его выглядеть следующим образом:

CourseContents
{
     int CourseId; // Foreign-Key to Courses.Id
     int Page;     // Foreign-Key to either Topic.Id or Quiz.Id
     int SNo;      // Sequence of this page (topic/quiz) in the course, much like page number in a book.
     int Type      // Type of the page i.e, Quiz or Topic. 
}

Есть ли способ, чтобы добиться этого в РСУБД?

Попытка решения

Один из подходов, я смотрю на это создание таблицы, чтобы создать уникальный идентификатор для данного элемента курса. Затем используйте его в картографических таблицах Курсов-Теме и курсы-викторине. Пожалуйста, обратитесь ниже:

CourseContents
{
    int Id;        // CourseContentId Primary-Key for this table
    int CourseId;  // Foreign key to Course.Id
    int SNo;       // Serial number of an item in this course;
}

CourseTopics
{
    int TopicId;             // Foreign-Key to Topics.Id
    int CourseContentsId;    // Foreign-Key to CourseContents.Id
}

CourseQuizzes
{
    int QuizId;               // Foreign-Key to Quizzes.Id
    int CourseContentsId;     // Serial number of the quiz in the course
}

Проблема: CourseContentId представляют определенную позицию (по теме / Quiz) в том или ином курсе. Две вещи не могут занимать такое же положение в последовательности курса, следовательно , один CourseContentId должен быть связан только с одним пунктом в или CourseTopics или CourseQuizzes. Как мы можем поставить ограничение уникальности на CourseContentsId через две таблицы?

Дальнейшее добавление

Вышесказанная проблема может быть решена путем добавления столбца ContentType в CourseContents, CourseTopics и CourseQuizzes колонка. Тогда , применяя проверочное ограничение на столах , чтобы убедиться:

  • CourseContents имеет уникальное сочетание CourseContentId и ContentType.
  • CourseTopics & CourseQuizzes должны иметь тот же тип контента в поперечнике.
  • Добавление иностранного ключа, ссылающийся CourseContents (CourseContentId, ТипСодержимый) в CourseTopics и CourseQuizzes таблиц.

Это будет гарантировать, что CourseContentId не будут появляться в обеих таблицах.

Задан 27/11/2018 в 14:59
источник пользователем
На других языках...                            


2 ответов

голоса
0

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 (другими словами, курс и 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. Только разница здесь мы имеем «Q» CourseContentType.

Наконец, чтобы упростить обработку запросов, мы можем создать представление, которое соединяет эти таблицы вместе. Для, например, вид ниже списка будет: CourseId, SnO, ТипСодержимый, 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);

Преимущества, которые я чувствую с этим подходом являются:

  1. Эта структура следует наследованию, что означает, что мы можем поддерживать больше типов контента, просто добавив еще одну таблицы и изменение CourseContentType проверочного ограничения в таблице CourseContents.
  2. Для данного CourseId и SnO. я также знаю, тип содержимого. Это, безусловно, поможет в коде приложения.

Примечание: Проверьте ограничение не работает в MySQL. Для этого нужно использовать триггеры вместо этого.

Ответил 06/12/2018 в 10:35
источник пользователем

голоса
0

В CourseContentId представляет определенную позицию (по теме / викторине) в определенном курсе.

CourseTopics
{
    int TopicId;             // Foreign-Key to Topics.Id

    int CourseContentsId;  -- first of 3-part FK
    int Page;              -- added
    int SNo;               -- added
    PRIMARY KEY(TopicId, CourseContentsId, Page, SNo), -- for JOINing one way
    INDEX      (CourseContentsId, Page, SNo, TopicId)  -- for JOINing the otehr way
}

В то же время, ...

Я предполагаю , что ваша главная задача воплощается в этой одной строке:

INT Page; // Внешнеэкономическая ключ к любому Topic.Id или Quiz.Id

Это нецелесообразно. Решение состоит в том, чтобы иметь единую таблицу для Topicи Pageи дифференцировать оттуда.

Ответил 29/11/2018 в 20:46
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more