2013-03-05 16 views
5

Prima lasciatemi dire che sto usando MySQL (non transazionale) e che questo non può essere modificato. Inoltre, ho semplificato le tabelle qui per brevità e chiarezza.Come posso risolvere un'associazione polimorfa a tre vie?

In questo esempio una "lezione" comprende gli attributi interni e gli attributi esterni con i propri attributi "Letture". 'Letture' ha i propri attributi dipendenti dalla chiave e tre attributi esterni distinti (le fonti di lettura).

Voglio evitare l'associazione polimorfica che si arresta qui ma non riesco a girarmi intorno. In questo esempio 'sourceId' nella tabella 'Reading' conterrà l'id da una delle tre tabelle "ExternalURL", "InternalURL" e "Book". Inoltre, il campo "polytable" conterrebbe il nome della tabella da cui proviene l'id "summenzionato".

Qualcuno può prendere un momento per spiegare come risolvere questo RI di mantenimento o è possibile che nell'interesse dell'efficienza debba essere lasciato?

Grazie per il vostro tempo e la considerazione,

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

risposta

7

Hai almeno un paio di opzioni per preservare RI:

  1. Aggiungi diverse colonne FK nullable in Reading , uno per ogni tipo di lettura. Solo uno di questi dovrebbe essere non nullo.

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

    far rispettare che proprio una delle colonne chiave esterna non è nullo è un compito per un trigger, oppure che avrei dovuto farlo nel codice dell'applicazione. Ma almeno puoi definire le chiavi esterne.

  2. Aggiungere un superabile Readable che è un genitore di ciascuno degli altri specifici tipi leggibili.

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

    Quindi fare Leggere anche il riferimento leggibile.

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

    descrivo questa soluzione in modo più dettagliato nella mia risposta a Why can you not have a foreign key in a polymorphic association?.

+0

Ciao Bill, prima vorrei ringraziarti per la tua pronta risposta. In secondo luogo, non capisco l'opzione due, ma sembra che il sé impone il RI a differenza del primo, il che penso che avresti bisogno di supportarlo con la logica programmatica per assicurarmi che solo uno non sia nullo. Chiamami denso 'Readable_type' nella tabella 'Readable' contiene 'B' per il libro, 'I' per interno e 'E' per esterno? Perché la chiave primaria di Book non viene incrementata automaticamente? Come aggiungo una nuova lettura di un particolare tipo? So che sei impegnato, ma se potessi fornire ulteriori spiegazioni sul come e sul perché lo apprezzerei molto. Grazie. – mpactMEDIA

+0

Ho aggiunto un collegamento a una risposta passata che ho scritto, in cui approfondisco la soluzione n. 2. –

+0

Grazie mille Bill molto apprezzato. – mpactMEDIA