2013-03-05 59 views
5

首先让我说我正在使用MySQL(不是事务),并且这是不能改变的。此外,为简洁明了起见,我在此简化了表格。如何解决三向多态关联?

在本例中,“课程”由它的内部属性和外部属性组成,并带有属性'Readings'。 “阅读”有它自己的关键依赖属性和三个不同的外部属性(阅读来源)。

我想避免在这里出现的多态关联,但我无法将其包裹在它周围。在此示例中,'Reading'表中的'sourceId'将包含来自三个表“ExternalURL”,“InternalURL”和“Book”之一的ID。此外,字段“polytable”将包含上述“id”来自的表名称。

有人可以花一点时间来解释如何解决这个维护RI还是有可能为了效率的利益,它应该留下?

谢谢您的时间和考虑,

     ------------- 
         | ExternalURL | 
         ------------- 
         | id   | 
         | badlink  | 
         | url   | 
         |    | 
         |    | 
         ------------- 
          | 
          | 
          | 
         /\ 
------------   -------------   ------------- 
| Lesson  |-------<| Reading  |>-------| InternalURL | 
------------   -------------   ------------- 
| id   |  | id   |  | id   | 
| label  |  | lessonId |  | url   | 
| summary |  | sourceId |  |    | 
| lessonOrder|  | polytable |  |    | 
| active  |  | label  |  |    | 
------------   -------------   ------------- 
          \/
          | 
          | 
         ------------ 
         | Book  | 
         ------------ 
         | id   | 
         | label  | 
         | summary | 
         | lessonOrder| 
         | active  | 
         ------------ 

回答

7

您至少有几个选项来保存RI:

  1. 添加几个可为空FK列Reading ,每种阅读类型一个。其中只有一个应该是非空的。

    CREATE TABLE Reading (
        id INT AUTO_INCREMENT PRIMARY KEY, 
        lessonId INT NOT NULL, 
        bookId INT NULL, 
        externalUrlId INT NULL, 
        internalUrlId INT NULL, 
        FOREIGN KEY (bookId) REFERENCES Book(id), 
        FOREIGN KEY (externalUrlId) REFERENCES ExternalUrl(id), 
        FOREIGN KEY (internalUrlId) REFERENCES InternalUrl(id) 
    ); 
    

    强制执行外键列的恰好是一个非空是一个trigger任务,否则你就必须这样做,在应用程序代码。但至少你可以定义外键。

  2. 添加一个超类型Readable,它是每个其他特定可读类型的父亲。

    CREATE TABLE Readable (
        id INT AUTO_INCREMENT PRIMARY KEY, 
        readable_type CHAR(1) NOT NULL, 
        UNIQUE KEY (id, readable_type) 
    ); 
    
    CREATE TABLE Book (
        id INT PRIMARY KEY, -- not AUTO_INCREMENT 
        readable_type CHAR(1) NOT NULL, -- must be 'B' 
        FOREIGN KEY (id, readable_type) REFERENCES Readable(id, readable_type) 
    ); 
    
    ... similar tables for ExternalUrl and InternalUrl... 
    

    然后使阅读也引用可读。

    CREATE TABLE Reading (
        id INT AUTO_INCREMENT PRIMARY KEY, 
        lessonId INT NOT NULL, 
        sourceId INT NOT NULL, 
        FOREIGN KEY (sourceId) REFERENCES Readable(id) 
    ); 
    

    我在我对Why can you not have a foreign key in a polymorphic association?的回答中更详细地描述了这个解决方案。

+0

嗨比尔,首先让我感谢您的及时回复。其次,我不明白选项二,但它看起来像自我强制RI不同于第一种,我认为你需要用程序逻辑来支持它,以确保只有一个不为空。给我打电话吧。 'Readable'表中的'readable_type'是否包含书'B','I'是内部,'E'是否包含外部?为什么Book的主键不能自动增量?如何添加特定类型的新阅读?我知道你很忙,但如果你可以提供进一步的解释,我将如何以及为什么我会非常感激。谢谢。 – mpactMEDIA 2013-03-05 00:42:39

+0

我已经添加了一个链接到我写的过去的答案,其中我详细介绍了解决方案#2。 – 2013-03-05 02:46:03

+0

谢谢比尔非常感谢。 – mpactMEDIA 2013-03-05 03:47:17