Problem bei Datenbankdesign

Matus

Neuer Benutzer
Beiträge
4
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
 
Werbung:

akretschmer

Datenbank-Guru
Beiträge
9.851
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


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
 

Matus

Neuer Benutzer
Beiträge
4
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.
 

akretschmer

Datenbank-Guru
Beiträge
9.851
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.

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.
 

Matus

Neuer Benutzer
Beiträge
4
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?
 

akretschmer

Datenbank-Guru
Beiträge
9.851
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?

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

Matus

Neuer Benutzer
Beiträge
4
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.
 
Oben