【问题标题】:How can I resolve a three-way polymorphic association?如何解决三向多态关联?
【发布时间】:2013-02-19 05:56:51
【问题描述】:

首先让我说我正在使用 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     |
                       ------------ 

【问题讨论】:

    标签: mysql normalization polymorphic-associations


    【解决方案1】:

    您至少有两个选择来保留 RI:

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

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

      然后让 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)
      );
      

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

    【讨论】:

    • 嗨,比尔,首先让我感谢您的及时回复。其次,我不明白选项二,但它看起来像第一个不同的是它自己强制执行 RI,我认为你需要用程序逻辑来支持它,以确保只有一个不为空。叫我密集。表'Readable'中的'readable_type'是否包含书的'B',内部的'I'和外部的'E'?为什么Book的主键不自增?如何添加特定类型的新阅读?我知道你很忙,但如果你能提供进一步的解释,我将不胜感激。谢谢。
    • 我添加了一个指向我写的过去答案的链接,其中我将详细介绍解决方案 #2。
    • 非常感谢比尔。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-14
    • 1970-01-01
    • 2023-03-05
    相关资源
    最近更新 更多