How can I resolve a three-way polymorphic association?

半城伤御伤魂 提交于 2020-01-01 10:58:31

问题


First let me say I am using MySQL (not transactional) and that this can't be changed. Also, I have simplified the tables here for brevity and clarity.

In this example a 'Lesson' is comprised of it's internal attributes and an external attributes with it's own attributes 'Readings'. 'Readings' has it's own key dependent attributes and three distinct external attributes (the reading sources).

I want to avoid the polymorphic association that arrises here but am unable to wrap my head around it. In this example 'sourceId' in table 'Reading' would contain the id from one of three tables "ExternalURL", "InternalURL" and "Book". Also, the field "polytable" would contain the table name that the aforementioned "id" came from.

Can someone take a moment to please explain how to resolve this maintaining RI or is it possible that in the interest of efficiency that it should be left?

Thank you for your time and consideration,

Tim

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

回答1:


You have at least a couple of options to preserve RI:

  1. Add several nullable FK columns in Reading, one for each reading type. Only one of these should be non-null.

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

    Enforcing that exactly one of the foreign key columns is non-null is a task for a trigger, or else you'd have to do it in application code. But at least you can define the foreign keys.

  2. Add a supertable Readable which is a parent of each of the other specific readable types.

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

    Then make Reading also reference Readable.

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

    I describe this solution in more detail in my answer to Why can you not have a foreign key in a polymorphic association?.



来源:https://stackoverflow.com/questions/15213530/how-can-i-resolve-a-three-way-polymorphic-association

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!