5

首先让我说我正在使用 MySQL(不是事务性的)并且这是无法更改的。此外,为了简洁明了,我在这里简化了表格。

在此示例中,“课程”由其内部属性和具有其自身属性“读数”的外部属性组成。“阅读”有它自己的关键依赖属性和三个不同的外部属性(阅读源)。

我想避免这里出现的多态关联,但我无法理解它。在此示例中,表“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     |
                       ------------ 
4

1 回答 1

8

您至少有几个选项可以保留 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)
    );
    

    强制其中一个外键列不为空是触发器的任务,否则您必须在应用程序代码中执行此操作。但至少你可以定义外键。

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

    然后让 Reading 也参考 Readable。

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

    我在回答为什么在多态关联中不能有外键?.

于 2013-03-05T00:21:45.923 回答