TobiasBuschi: Datenbankdesign für perfekte Text-Tabelle

hallo allerseits

Ich habe mir schon viele Gedanken darüber gemacht, wie ich in meinem PHP-Framework, dass ich am basteln bin, die Text-Tabelle perfekt organisiere.

Diese Text-Tabelle wird Texte enthalten welche von verschiedenen anderen Tabellen referenziert werden können.

Ein Text soll mehrsprachig sein können und es sollten Versionen/Revisionen vom selben text gemacht werden können.

In einer alten Version habe ich es so gelöst(ohne Versionisierung):

PK:id | de     | en      | fr      | it
--------------------------------------
     2 | hallo  | hello   | bonjout | ciou
    11 | mutter | mother  | mere    | mama

eine Abfrage war zum Beispiel:

Select $lang AS text
FROM texts
WHERE id = 2
-> hallo

Nun bin ich aber nicht mehr überzeugt von dieser Lösung mit den Sprachen-Spalten.

Jetzt bin ich eher für diese Variante:

PK:id | PK:lang | text
--------------------------
     2 |      de | hallo
     2 |      en | hello
    11 |      de | mutter
    11 |      en | mother
      .        .       .
bsp.Abfrage :
------------
Select text FROM texts WHERE lang = '$lang' AND id = 2
->hallo

Beispiel für eine Abfrage mittels LEFT JOIN
--------------------------
Select
     pages.*,
     texts.text
FROM
     pages
     LEFT JOIN texts ON pages.title_text_id = texts.id AND lang = $lang
WHERE pages.id = 5

Dazu kommen jetzt noch die Versionen / Revisionen

PK:id | PK:lang | PK:revision | text
--------------------------
     2 |      de |         0   | hallo                      //// revision = 0 entspricht aktuell
     2 |      de |         1   | Sehr geehrter Herr
     2 |      de |         2   | Sehr geehrte Damen und Herren
     2 |      de |         3   | hallo
     2 |      de |         4   | Hallo
     2 |      en |         0   | hello                    //// revision = 0 entspricht aktuell
     2 |      en |         1   | Dear Mister
     2 |      en |         2   | Dear
     2 |      en |         3   | hi

Die Revision 0, so habe ich gedacht, benutze ich für den aktuellen Text.
Oder soll ich, um den aktuellen Wert zu bestimmen eine zusätzliche Spalte anlegen? (Platzverschwendung?)
Oder gar eine zusätzliche Tabelle die den aktuellen text bestimmt?
(zu Aufwändig? ich denke schon)

Oder ganz anders??
Ich will es wirklich perfekt haben!!!!!

Ich hoffe man kann meinen Gedankengängen noch folgen.

Besten dank für jede Bemerkung.

mfg Tobias

  1. hi,

    Die Revision 0, so habe ich gedacht, benutze ich für den aktuellen Text.

    Das halte ich für unklug - da müsstest du ja jedes Mal beim Einfügen einer neuen Textversion alle anderen Texte mit dieser ID updaten, und deren Revision um eins hochsetzen.

    Zähle die Revision doch fortlaufend hoch - und lese den mit der höchsten Revisionsnummer als den aktuellen aus.

    gruß,
    wahsaga

    --
    /voodoo.css:
    #GeorgeWBush { position:absolute; bottom:-6ft; }
    1. Hallo wahsaga

      Die Revision 0, so habe ich gedacht, benutze ich für den aktuellen Text.

      Das halte ich für unklug - da müsstest du ja jedes Mal beim Einfügen einer neuen Textversion alle anderen Texte mit dieser ID updaten, und deren Revision um eins hochsetzen.

      Ich muss bei einer neuen Text-Version einfach die max(revision) von dem entsprechenden Text (id) und der ensprechenden Sprache (lang) ermitteln und für die neue Version eins dazuzählen:

      Update auf eine neue Version sieht nach meiner Idee so aus:

      INSERT INTO texts
      SET
          text = 'blabla',
          id = $id,
          lang = $lang
          revision = 1 + (SELECT max(revision) FROM texts WHERE id = $id AND lang = $lang)

      Eine Revision (z.B. revision 4) als aktuell definieren so:

      DELETE FROM texts WHERE id = $id AND lang = $lang AND revision = 0; // bisher aktueller löschen

      INSERT INTO texts
      SET
          text = (SELECT text FROM texts WHERE id = $id AND lang = $lang AND revision = 4),
          id = $id,
          lang = $lang
          revision = 0

      -> ich mache eine Kopie der ausgewählten Revision.

      Zähle die Revision doch fortlaufend hoch - und lese den mit der höchsten Revisionsnummer als den aktuellen aus.

      meinst du so?:

      PK:id | PK:lang |    revision | text
      -------------------------------------------------------------------------------
           2 |      de |         1   | Sehr geehrter Herr
           2 |      de |         2   | Sehr geehrte Damen und Herren
           2 |      de |         3   | hallo
           2 |      de |         4   | Hallo           //// aktuell deutsch (hallo)
           2 |      en |         5   | Dear Mister
           2 |      en |         6   | hi
           2 |      en |         7   | Dear            //// aktuell englisch (hallo)
          11 |      de |         8   | mutter          //// aktuell deutsch (mutter)

      Beachte aber, dass die aktuelle Version nicht immer die neuste Revision sein muss.

      1. Oder eher so:

        PK:id | PK:lang | PK:revision | aktuell | text
         -------------------------------------------------------------------------------
              2 |      de |         1   |       0 | Sehr geehrter Herr
              2 |      de |         2   |       0 | Sehr geehrte Damen und Herren
              2 |      de |         3   |       1 | hallo
              2 |      de |         4   |       0 | Hallo           //// aktuell deutsch (hallo)
              2 |      en |         1   |       0 | Dear Mister
              2 |      en |         2   |       0 | hi
              2 |      en |         3   |       1 | Dear            //// aktuell englisch (hallo)
             11 |      de |         1   |       1 | mutter          //// aktuell deutsch (mutter)

        Wobei dann "von Hand" geprüft werden muss,
        dass nicht mehr als ein Text der selben ID und Sprache aktuell sein kann.

        1. Ich würde auch noch eine Art "key" hinzufügen um klar zu machen wofür der Text eigentlich steht. Macht das spätere auffinden und verwenden von Texten leichter

          PK:id | PK:lang | PK:revision | key            |aktuell | text  -------------------------------------------------------------------------------       2 |      de |         1   |greeting_male   |      0 | Sehr geehrter Herr       2 |      de |         2   |                |      0 | Sehr geehrte Herren       2 |      de |         3   |                |      1 | hallo       2 |      de |         4   |                |      0 | Hallo           //// aktuell deutsch (hallo)       2 |      en |         1   |                |      0 | Dear Mister       2 |      en |         2   |                |      0 | hi       2 |      en |         3   |                |      1 | Dear            //// aktuell englisch (hallo)      11 |      de |         1   |gretting_female |      1 | mutter          //// aktuell deutsch (mutter)      11 |      de |         1   |gretting_unisex |      1 | mutter          //// aktuell deutsch (mutter)

      2. hi,

        Ich muss bei einer neuen Text-Version einfach die max(revision) von dem entsprechenden Text (id) und der ensprechenden Sprache (lang) ermitteln und für die neue Version eins dazuzählen:

        Ja, OK.

        Eine Revision (z.B. revision 4) als aktuell definieren so:
        [...]
          -> ich mache eine Kopie der ausgewählten Revision.

        Hm, erscheint mir suboptimal. Damit hältst du den Datensatz ja bis auf dieses eine Kennzeichen komplett redundant vor.

        Beachte aber, dass die aktuelle Version nicht immer die neuste Revision sein muss.

        Gut, das war für mich auch noch nicht klar definiert.

        Dann würde ich aber wirklich aktuell als zusätzliches Kennzeichen führen.
        Neue/andere Revision auf aktuell setzen: Beim aktuellen (oder allen) DS das Kennzeichen aktuell auf 0 setzen, und anschließend beim neuen aktuellen auf 1 - o.ä.

        Transaktionssicherheit sollte dabei natürlich berücksichtigt bzw. eingeplant werden.
        Denn plötzlich mehr als einen aktuell(st)en Datensatz zu haben, käme doof.

        gruß,
        wahsaga

        --
        /voodoo.css:
        #GeorgeWBush { position:absolute; bottom:-6ft; }
        1. Transaktionssicherheit sollte dabei natürlich berücksichtigt bzw. eingeplant werden.
          Denn plötzlich mehr als einen aktuell(st)en Datensatz zu haben, käme doof.

          Ja genau, besten Dank!

          Ich denke ich mache es so, wenn niemand ein gutes Gegenargument bringen kann.