从多个表引用数据

62lalag4  于 2021-06-17  发布在  Mysql
关注(0)|答案(2)|浏览(253)

我有三个简单的实体:
课程就像一本书,一种可以销售的产品。课程实体表示课程,并具有各种属性,如持续时间、费用、作者、类型等。

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. 
}

在rdbms中有什么方法可以实现这一点吗?

尝试解决

我正在研究的一种方法是创建一个表来为给定的课程项创建唯一标识符。然后将其用于Map表格、课程主题和课程测验。请参考以下内容:

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表示特定课程中的特定位置(主题/测验)。两个项目不能在课程序列中占据相同的位置,因此一个coursecontentid必须与coursetopics或coursequizzes中的一个项目关联。如何在两个表中对coursecontentsid设置唯一约束?
进一步添加
上述问题可以通过在coursecontents、coursetopics和coursequizzes列中添加contenttype列来解决。然后对表应用check约束以确保:
coursecontents具有coursecontentid和contenttype的唯一组合。
课程主题和课程测验的内容类型必须相同。
在coursetopics&coursequizzes表中添加引用coursecontents(coursecontentid,contenttype)的外键。
这将确保coursecontentid不会出现在两个表中。

b91juud3

b91juud31#

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),
);

课程内容表为每个courseid和sno组合生成一个唯一的id(coursecontentsid),然后可以在topics&quizzes表中引用。由于有两个不同的表(主题和测验),我们将介绍另一个列,它标识链接到的内容类型(主题/测验)。通过对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)
);

课程主题表是主题和课程之间的Map表(我们有课程和主题表之间的多对多关系)。coursecontents表的外键和主键确保每个coursecontents有一个条目(换句话说,course&sno)。该表将coursecontenttype限制为仅接受“t”,这意味着给定的coursecontentid必须具有topic的内容类型才能与主题链接。

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)上的内容、页面上的内容类型(主题或测验)以及内容的id。

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);

我觉得这种方法的优点是:
这个结构遵循继承,这意味着我们可以通过添加另一个表和修改coursecontents表中的coursecontenttype检查约束来支持更多的内容类型。
对于给定的课程ID和sno。我也知道内容类型。这当然会对应用程序代码有所帮助。
注意:check约束在mysql中不起作用。因此,我们需要使用触发器。

9nvpjoqh

9nvpjoqh2#

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页;//topic.id或quick.id的外键
那是不切实际的。解决办法是为每个人提供一个表 Topic 以及 Page 从那里区别开来。

相关问题