2013-03-05 31 views
5

Po pierwsze pozwól mi powiedzieć, że używam MySQL (nie transakcyjnego) i że nie można tego zmienić. Uprościliśmy tu także tabele dla zwięzłości i przejrzystości.Jak mogę rozwiązać trójdrożne stowarzyszenie polimorficzne?

W tym przykładzie "Lekcja" składa się z wewnętrznych atrybutów i zewnętrznych atrybutów z własnymi atrybutami "Odczyty". "Odczyty" mają własne kluczowe atrybuty zależne i trzy odrębne cechy zewnętrzne (źródła czytania).

Chcę uniknąć polimorficznego skojarzenia, które tu przybywa, ale nie jestem w stanie owinąć się wokół niego. W tym przykładzie "sourceId" w tabeli "Reading" zawierałby identyfikator z jednej z trzech tabel "ExternalURL", "InternalURL" i "Book". Również pole "polytable" będzie zawierało nazwę tabeli, z której pochodzi wspomniany wcześniej "id".

Czy ktoś może poświęcić chwilę, aby wyjaśnić, w jaki sposób rozwiązać ten problem z zachowaniem wskaźnika RI, czy też jest możliwe, że w interesie efektywności powinno ono zostać?

Dziękuję za poświęcony czas i uwagę,

Tima

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

Odpowiedz

7

mieć co najmniej kilka opcji, aby zachować RI:

  1. Dodaj kilka zerowalne kolumny FK w Reading , po jednym dla każdego rodzaju czytania. Tylko jeden z nich powinien mieć wartość inną niż 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) 
    ); 
    

    Egzekwowanie że dokładnie jedna z kolumn klucza obcego jest niezerowe to zadanie dla trigger, albo trzeba by zrobić to w kodzie aplikacji. Ale przynajmniej możesz zdefiniować klucze obce.

  2. Dodaj supertable Readable, który jest nadrzędny dla każdego z innych typów czytelnego określonego.

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

    Następnie dokonać odczytu Reading również.

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

    opiszę to rozwiązanie bardziej szczegółowo w mojej odpowiedzi na Why can you not have a foreign key in a polymorphic association?.

+0

Witam Bill, najpierw pozwól mi podziękować za szybką odpowiedź. Po drugie, nie rozumiem opcji drugiej, ale wygląda na to, że samo wymusza RI w przeciwieństwie do pierwszego, co, jak sądzę, musicie wesprzeć logiką programową, aby upewnić się, że tylko jedna nie jest zerowa. Zadzwoń do mnie gęsty. Czy "readable_type" w tabeli "Readable" zawiera "B" dla książki, "I" dla wewnętrznej i "E" dla zewnętrznej? Dlaczego klucz podstawowy Book nie jest automatycznie zwiększany? Jak dodać nową lekturę określonego typu? Wiem, że jesteś zajęty, ale jeśli mógłbyś podać dalsze wyjaśnienie, w jaki sposób i dlaczego byłbym bardzo wdzięczny. Dziękuję Ci. – mpactMEDIA

+0

Dodałem link do poprzedniej odpowiedzi, którą napisałem, w której bardziej szczegółowo omawiam rozwiązanie # 2. –

+0

Dziękuję Bill bardzo doceniany. – mpactMEDIA