Information ausblenden
Willkommen im Forum für alle Datenbanken! Registriere Dich kostenlos und diskutiere über DBs wie Mysql, MariaDB, Oracle, Sql-Server, Postgres, Access uvm

Problem bei Datenbankdesign

Dieses Thema im Forum "Datenmodellierung, Datenbank-Design" wurde erstellt von Matus, 29 Juli 2013.

  1. Matus

    Matus Neuer Benutzer

    Hiho,

    ich schreibe derzeit mit ZF2 ein Programm.
    Dabei brauch ich natürlich auch eine Datenbank und genau da
    liegt der Hund begraben.
    Ich bin beim Design auf ein Problem gestoßen. Ich habe eine Tabelle
    für Einträge. Die ID ist die threadId. Um einen Eintrag von einer
    Antwort zu unterscheiden gibt es die parentId.
    Nun die große Frage, wie definiere ich die Relationen korrekt?
    Benötige ich eine Kreuztabelle oder reicht es eine Many-To-One
    beziehung zwischen parentId und threadId zu erstellen.

    Das korrekte Design ist für mich besonders wichtig da ich mit Doctrine2
    arbeite und ansonsten das Mapping und das abrufen der zum Elterneintrag gehörigen Antworten nicht korrekt funktioniert ohne dafür eine extra Abfrage zu erstellen.

    Danke für eure Hilfe im Voraus
     
  2. akretschmer

    akretschmer Datenbank-Guru


    Da reicht eine Tabell aus, die aber auf sich selbst referenziert. Demo:

    Code:
    test=*# \d matus;
          Table "public.matus"
      Column   |  Type   | Modifiers
    -----------+---------+-----------
     id        | integer | not null
     parent    | integer |
     thread_id | integer |
     content   | text    |
    Indexes:
        "matus_pkey" PRIMARY KEY, btree (id)
    Foreign-key constraints:
        "matus_parent_fkey" FOREIGN KEY (parent) REFERENCES matus(id)
    Referenced by:
        TABLE "matus" CONSTRAINT "matus_parent_fkey" FOREIGN KEY (parent) REFERENCES matus(id)
    
    test=*# select * from matus;
     id | parent | thread_id |               content
    ----+--------+-----------+-------------------------------------
      1 |        |         1 | frage 1
      2 |      1 |         1 | antwort 1 auf frage 1
      3 |      1 |         1 | antwort 2 auf frage 1
      4 |      3 |         1 | antwort 1 auf antwort 2 auf frage 1
      5 |        |         2 | frage 2
      6 |      5 |         2 | antwort 1 auf frage 2
    (6 rows)
    
    Time: 0,206 ms
    test=*# with recursive r as (select id, parent, thread_id, content, 0 as level from matus where parent is null union all select m.id, m.parent, m.thread_id, m.content, r.level+1 from matus m join r on m.parent=r.id) select id, parent, thread_id, repeat('-',level) || '-> ' || content from r order by thread_id,level, parent;
     id | parent | thread_id |                 ?column?
    ----+--------+-----------+------------------------------------------
      1 |        |         1 | -> frage 1
      2 |      1 |         1 | --> antwort 1 auf frage 1
      3 |      1 |         1 | --> antwort 2 auf frage 1
      4 |      3 |         1 | ---> antwort 1 auf antwort 2 auf frage 1
      5 |        |         2 | -> frage 2
      6 |      5 |         2 | --> antwort 1 auf frage 2
    (6 rows)
    
    Time: 0,571 ms
    
    Das ist mit PostgreSQL gemacht. Falls Du es mit MySQL versuchen willst: laß es , es geht damit nicht. Oraggle sollte es faktisch 1:1 auch so gehen, M$SQL weiß ich nicht.

    Andreas
     
  3. Matus

    Matus Neuer Benutzer

    Die Sache ist das ich mit MySQL arbeite. PostgreSQL will ich wegen einem Projekt nicht auf meinem Server extra installieren.
    Ich hab auch schon einmal gesehen das eine selbstreferenzierte Tabelle mit MySQL (InnoDB) funktioniert hat nur leider
    habe ich auf diese keinen zugriff um mir das da genauer anzuschauen. Und da ich halt mit Doctrine arbeite wäre dann das auswerten
    auch total einfach. Aufruf in PHP wäre dann ja sowas wie $thread->getChilds()->getValues(); und genau das will ich.
    Derzeit muss ich eine extra Abfrage machen in der ich speziell alle Threads mit der passenden parentId ausgeben lasse.
     
  4. akretschmer

    akretschmer Datenbank-Guru

    Der Part sollte faktisch identisch zu PostgreSQL sein.

    Was in MySQL nicht geht: die rekursive Abfrage. Mit solchen Abfragen kannst Du die Bäume da hoch und runter rennen - alles innheralb der DB.
     
  5. Matus

    Matus Neuer Benutzer

    gut das macht ja Doctrine2 für mich :)
    Danke erstmal. Sollte noch eine Frage auftreten melde ich mich nochmal.

    Edit:
    Das Problem das ich bei dem Schema habe ist das die Id gleicheitig de ThreadId ist.
    Ist dann das selbst referenzieren auch möglich oder brauch ich dann doch eine weitere Spalte?
     
  6. akretschmer

    akretschmer Datenbank-Guru

    Die ID sollte ja ein Primary Key sein, für die Referenzierung. Damit eindeuting. Das würde jeden Deiner Threads auf einen Beitrag begrenzen. Ich glaube, das willst Du nicht.
     
  7. Matus

    Matus Neuer Benutzer

    Die Lösung ist jetzt zur Unterscheidung eine Selbstreferenz gemischt mit einer Many-to-Many Beziehung über eine Kreuztabelle.
    Da bin ich an eine Grenze (oder Fehler) von Doctrine2 gestoßen. Bei Many-to-One Beziehungen liefert es nämlich nicht wie erwartet das Objekt zurück.
    So kann ich nun aber per Lazy-Loading bei Bedarf alle Kind-Elemente einfach Abfragen und sogar in denen suchen und Änderungen vornehmen und brauch nur die Eltern Entity speichern. Durchs Cascade wird dann alles gespeichert.
     
Die Seite wird geladen...

Diese Seite empfehlen

  1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies.
    Information ausblenden