John M.: Arrays in MySQL-Datenbank speichern und auslesen

Hallo Leute, ich hab eine Frage:

Ich möchte in einer Datenbank mit PHP Bilder speichern und dazugehörig noch Schlagwörter. Dabei gibt es sagen wir mal eine Begrenzung von maximal 50 Schlagwörtern pro Bild. Aber wie kann ich diese Schlagwörter am besten speichern?
Ich hab mal nach einer Möglichkeit gesucht, aber anscheinend gibt es nur die Funktion serialize(), die dafür geeignet ist. Die Funktion macht das Array zu einem String und unserialize() macht den String wieder zu einem Array. Das Problem ist aber jetzt, wenn ich nach Bildern mit dem Schlagwort "Sonnenuntergang" suche, kann ich ja keine WHERE-Abfrage mehr machen.
Cool wäre so etwas:

"SELECT 'image' FROM bilder WHERE schlagwort CONTAIN 'Sonnenuntergang'"

oder soetwas. Schlagwort ist dann eine Spalte vom Typ "Array" und CONTAIN sollte bedeuten, dass im Array "Sonnenuntergang" vorhanden ist. Wisst ihr so eine MySQL-Syntax? Falls es keine gibt (was ich leider glaube, denn ich habe nichts dazu gefunden), wie kann ich das sonst umsetzen? Serialize() Möchte ich nicht verwenden, wenn man nicht mehr WHERE benutzen kann.

Ich danke euch für das Angucken und ggf. die Hilfe

MFG.

  1. Hallo

    Schlagwort ist dann eine Spalte vom Typ "Array" und CONTAIN sollte bedeuten, dass im Array "Sonnenuntergang" vorhanden ist. Wisst ihr so eine MySQL-Syntax?

    Gibt es in MySQL derzeit nicht, in PostgreSQL dagegen schon.

    Falls es keine gibt (was ich leider glaube, denn ich habe nichts dazu gefunden), wie kann ich das sonst umsetzen?

    wie üblich. Normalisiere Deine Daten und speichere diese atomar ab.
    Sprich: Verknüpfe Deine Schlagworttabelle mit der Tabelle der Bilder.

    Ein Schlagwort kann zu mehreren Bildern passen. Einem Bild können mehrere Schlagworte zugeordnet sein, d.h. eine ganz normal m:n-Beziehung.

    Freundliche Grüße

    Vinzenz

    1. Hallo

      Schlagwort ist dann eine Spalte vom Typ "Array" und CONTAIN sollte bedeuten, dass im Array "Sonnenuntergang" vorhanden ist. Wisst ihr so eine MySQL-Syntax?

      Gibt es in MySQL derzeit nicht, in PostgreSQL dagegen schon.

      Ich habe damit noch nie etwas zu tun gehabt und bis jetzt immer nur MySQL verwendet. Hier in SELFHTML (http://forum.de.selfhtml.org/archiv/2006/1/t122093/) stehen ja nun ein paar Vorteile und Nachteile. Meinst du es lohnt sich auf PostgreSQL zu setzen, weil ich da sozusagen mit Arrays arbeiten kann, obwohl die Performance schlechter ist? (Ist das überhaupt noch aktuell?) Oder wäre das mit Arrays falsch designed und dein Vorschlag unten wäre die beste Lösung?

      Falls es keine gibt (was ich leider glaube, denn ich habe nichts dazu gefunden), wie kann ich das sonst umsetzen?

      wie üblich. Normalisiere Deine Daten und speichere diese atomar ab.
      Sprich: Verknüpfe Deine Schlagworttabelle mit der Tabelle der Bilder.

      Ein Schlagwort kann zu mehreren Bildern passen. Einem Bild können mehrere Schlagworte zugeordnet sein, d.h. eine ganz normal m:n-Beziehung.

      Das verstehe ich nicht ganz. Also schlägst du vor, dass ich zwei Tabellen mache, einen Mit den Bildern, die dann die Bilder enthält, aber was noch?
      Und eine Tabelle wo alle Schlagwörter aufgeführt sind (die wird es sowieso geben)? Aber wie verknüpfe ich die bequem miteinander?

      Ich möchte nicht soetwas:

      Tabelle bilder
      Bild | Schlagwort1 | Schlagwort2 | Schlagwort3 | ... | Bildgröße | ...

      Sondern eben

      Tabelle bilder
      Bild | Schlagwörter[] | Bildgröße | ...

      Natürlich würde bei Schlagwörter[] dann eben "0 => 5, 1 => 24, 2 => 37", wobei 5, 24 und 37 dann wiederum für die ID eines bestimmten Schlagworts stehen.

      Nur wie bekomme ich das jetzt kompfortabel hin?

      1. Hallo

        Und eine Tabelle wo alle Schlagwörter aufgeführt sind (die wird es sowieso geben)? Aber wie verknüpfe ich die bequem miteinander?

        siehe Toms Beitrag.

        Ich möchte nicht soetwas:

        Bild | Schlagwort1 | Schlagwort2 | Schlagwort3 | ... | Bildgröße | ...

        Nein. Klar.

        Sondern eben

        Tabelle bilder
        Bild | Schlagwörter[] | Bildgröße | ...

        Nein, das solltest Du ebenfalls nicht wollen. Daten sollten atomar vorliegen.

        Lesetipps in SELFHTML aktuell:
        Einführung in Joins
        Fortgeschrittene Jointechniken

        Freundliche Grüße

        Vinzenz

  2. Hello,

    das ist ein gutes Beipiel für eine n:m Beziehung

    bild                   bild_aspekt              aspekt
    ----                   -----------              -----------
    id_bild ------------>  id_bild          +---->  id_aspekt
    bildname               id_aspekt -------+       aspektbez

    Nun kannst Du jedem Bild beliebig viele Schlagworte zuordnen und die Schlagworte können beliebig vielen Bildern zugeordnet werden.

    Um die Anzahl der Schalgworte pro Bild ggf. zu begrenzen, werden zusätzliche Mechanismen benötigt.

    Liebe Grüße

    Tom

    --
    Coming Back soon

    1. Hello,

      bei einer begrenzten Anzahl außerdem schon bei der Programmierung feststehender Schlagworte könnte man auch noch die Verwendung einer Spalte vom Typ SET http://dev.mysql.com/doc/refman/5.1/de/set.html in Erwägung ziehen.
      Sie ist aber begrenzt auf 64 unterschiedliche Werte und meistens bereut man es, wenn man dann später etwas ändern muss.

      Liebe Grüße

      Tom

      --
      Coming Back soon

      1. Hi, Tom, du warst die letzten 6 Wochen nicht wirklich erreichbar, meld dich doch bitte mal bei mir. :)  Du solltest meine eMail in deinem Postfach im Zusammenhang mit CPU/Board finden. ;)

        Ciao, Frank

    2. Hello,

      das ist ein gutes Beipiel für eine n:m Beziehung

      bild                   bild_aspekt              aspekt
      ----                   -----------              -----------
      id_bild ------------>  id_bild          +---->  id_aspekt
      bildname               id_aspekt -------+       aspektbez

      Nun kannst Du jedem Bild beliebig viele Schlagworte zuordnen und die Schlagworte können beliebig vielen Bildern zugeordnet werden.

      Sorry, versteh ich nicht so ganz. Kannst du es mal an folgendem Beispiel erklären?:

      Das Bild heißt "schönes_Bild", soll die Schlagworte "Sonnenuntergang", "Meer" und "Strand" haben und insgesamt gibt es die Schlagworte "Sonnenuntergang", "Meer", "Strand", "Düne", "Wolken".

      Dann sehen der erste Datensatz ja so aus:

      bild
      ----
      1 (id_bild)
      "schönes_Bild" (bildname)

      Aber dann? Was bedeutet "bild_aspekt"? Ich verstehe, dass id_bild dann identisch ist, aber was ist nun id_aspekt? Und was ist der dritte Datensatz?

      Und könntest du mir ein kleines INSERT Beispiel machen? Das wäre echt sehr nett von dir.

      Um die Anzahl der Schalgworte pro Bild ggf. zu begrenzen, werden zusätzliche Mechanismen benötigt.

      Darauf gehe ich gleich ein, wenn ich das verstanden habe. Man kann doch einfach abfragen, wieviele Schlagworte einem Bild zugeordnet sind oder nicht?

      1. Das Bild heißt "schönes_Bild", soll die Schlagworte "Sonnenuntergang", "Meer" und "Strand" haben und insgesamt gibt es die Schlagworte "Sonnenuntergang", "Meer", "Strand", "Düne", "Wolken".
        Dann sehen der erste Datensatz ja so aus:

        bild

        1 (id_bild)
        "schönes_Bild" (bildname)

        Genau.

        Aber dann? Was bedeutet "bild_aspekt"? Ich verstehe, dass id_bild dann identisch ist, aber was ist nun id_aspekt? Und was ist der dritte Datensatz?

        Du hast eine zweite Tabelle, welche die Beziehung zwischen dem Einzelbild und der dritten Tabelle (die mit den Kategorien) herstellt. Ohne diese 2. Tabelle ist das ganze Konzept Unsinn, da Du zwei völlig unabhängig nebeneinander stehende Tabellen hättest. Angenommen, Deine Kategorietabelle hätte folgende Einträge:

        Kat-ID | Kat-Bezeichnung  
          42   | Sinn des Lebens  
          666  | Number of the Beast
        

        Jetzt möchtest Du aus der Tabelle "Bilder" diese zwei Kategorien dem Bild mit der Nummer 3 zuordnen. Dann sähe Deine 2. Tabelle so aus:

        Bild-ID | Kat-ID  
          3     | 42  
          3     | 666
        

        Die hat für sich betrachtet erstmal keine Aussage, denn die bekommt sie erst durch Verknüpfung von Bild-ID mit Bild-ID aus der Tabelle "Bilder" und von Kat-ID mit Kat-ID aus der Tabelle "Kategorien".

        Und könntest du mir ein kleines INSERT Beispiel machen?

        Das bekommst Du selber hin:
        http://dev.mysql.com/doc/refman/5.1/de/insert.html

        Um die Anzahl der Schalgworte pro Bild ggf. zu begrenzen, werden zusätzliche Mechanismen benötigt.
        Darauf gehe ich gleich ein, wenn ich das verstanden habe. Man kann doch einfach abfragen, wieviele Schlagworte einem Bild zugeordnet sind oder nicht?

        Ja, kann man.

        Siechfred

        --
        Hinter den Kulissen passiert viel mehr, als man denkt, aber meistens nicht das, was man denkt.
        1. Das Bild heißt "schönes_Bild", soll die Schlagworte "Sonnenuntergang", "Meer" und "Strand" haben und insgesamt gibt es die Schlagworte "Sonnenuntergang", "Meer", "Strand", "Düne", "Wolken".
          Dann sehen der erste Datensatz ja so aus:

          bild

          1 (id_bild)
          "schönes_Bild" (bildname)

          Genau.

          Aber dann? Was bedeutet "bild_aspekt"? Ich verstehe, dass id_bild dann identisch ist, aber was ist nun id_aspekt? Und was ist der dritte Datensatz?

          Du hast eine zweite Tabelle, welche die Beziehung zwischen dem Einzelbild und der dritten Tabelle (die mit den Kategorien) herstellt. Ohne diese 2. Tabelle ist das ganze Konzept Unsinn, da Du zwei völlig unabhängig nebeneinander stehende Tabellen hättest. Angenommen, Deine Kategorietabelle hätte folgende Einträge:

          Kat-ID | Kat-Bezeichnung

          42   | Sinn des Lebens
            666  | Number of the Beast

          Ok, soweit klar. Ich habe erst jetzt verstanden, dass ihr mit "Kat" wohl Kategorie also ein Schlagwort meintet. Dann wäre diese Tabelle hier sozusagen eine Liste der Schlagworte.

          Jetzt möchtest Du aus der Tabelle "Bilder" diese zwei Kategorien dem Bild mit der Nummer 3 zuordnen. Dann sähe Deine 2. Tabelle so aus:

          Bild-ID | Kat-ID

          3     | 42
            3     | 666

          Stopp mal, welche Tabelle ist das jetzt? Wir haben ja nun Tabelle1 (da sind alle Bilder gespeichert, inkl. Auflösung) und Tabelle2 (da sind alle Schlagwörter gespeichert). Und diese Tabelle ist dann eine dritte Tabelle, in der bei jedem Datensatz eine Bild ID und eine Schlagwort ID stehen?

          Die hat für sich betrachtet erstmal keine Aussage, denn die bekommt sie erst durch Verknüpfung von Bild-ID mit Bild-ID aus der Tabelle "Bilder" und von Kat-ID mit Kat-ID aus der Tabelle "Kategorien".

          Dann mache ich also einen JOIN (Danke Vincent für die Artikel) und habe sozusagen eine virtuelle Tabelle, in der nun der Bildname, die Bild ID und die Schlagwörter stehen.

          Und könntest du mir ein kleines INSERT Beispiel machen?

          Das bekommst Du selber hin:
          http://dev.mysql.com/doc/refman/5.1/de/insert.html

          Nee, mir ist schon klar wie man einen normalen INSERT macht.
          Aber in diesem Fall ist das ja etwas anders.
          Angenommen ein User ordnet einem Bild 5 Schlagwörter zu.
          Dann ergänze ich die dritte Tabelle (Bild_ID, Schlagwort_ID) jeweils um 5 Einträge.
          Wenn ich dann anzeigen will, welche Schlagworte das Bild hat, mache ich einen JOIN, sodass alle Werte der Tabelle Bilder angezeigt werden, die die gleiche ID wie die Bild_ID in Tabelle3 haben und einen weiteren JOIN, sodass alle Datensätze aus Tabelle2 (die Tabelle wo die Schlagworte gespeichert sind) angezeigt werden, die die gleiche Schlagwort_ID wie die ID in Tabelle3 haben oder?

          Dann bekomme ich soetwas:

          virtuelle Tabelle (durch JOIN)
          -----------------

          Tabelle1.bild_id, Tabelle1.bild_name, Tabelle1.bild_auflösung, Tabelle2.schlagwort1
          Tabelle1.bild_id, Tabelle1.bild_name, Tabelle1.bild_auflösung, Tabelle2.schlagwort2
          Tabelle1.bild_id, Tabelle1.bild_name, Tabelle1.bild_auflösung, Tabelle2.schlagwort3

          Und nun gehe ich diese Datensätze in PHP durch und schnappe mir immer das entsprechende Schlagwort. Bzw. werde ich dann vorher nur die Schlagworte abfragen, nicht die anderen Daten.

          Aber jetzt habe ich ein Problem:
          Wenn ein User einem Bild ein neues Schlagwort zuordnen will, muss ich erstmal gucken, welche Schlagworte das Bild hat und überprüfen, ob das Schlagwort nicht schon dabei ist. Angenommen ich habe 10.000 Bilder von denen jedes 10 Schlagwörter hat, dann dauert das ja (durch die JOINS) extrem lange. Ist das überhaupt noch akzeptabel?

          Um die Anzahl der Schalgworte pro Bild ggf. zu begrenzen, werden zusätzliche Mechanismen benötigt.
          Darauf gehe ich gleich ein, wenn ich das verstanden habe. Man kann doch einfach abfragen, wieviele Schlagworte einem Bild zugeordnet sind oder nicht?

          Ja, kann man.

          So wie es jetzt ist, ist das ganze ja einfach, ich zähle wie oben die Schlagwörter und kann dann ja entscheiden.

          So, danke dass du mir hilfst, ich glaube es ist nicht einfach mit mir oder? :-)

          1. Ok, soweit klar. Ich habe erst jetzt verstanden, dass ihr mit "Kat" wohl Kategorie also ein Schlagwort meintet. Dann wäre diese Tabelle hier sozusagen eine Liste der Schlagworte.

            Genau.

            Jetzt möchtest Du aus der Tabelle "Bilder" diese zwei Kategorien dem Bild mit der Nummer 3 zuordnen. Dann sähe Deine 2. Tabelle so aus: [...]
            Stopp mal, welche Tabelle ist das jetzt? Wir haben ja nun Tabelle1 (da sind alle Bilder gespeichert, inkl. Auflösung) und Tabelle2 (da sind alle Schlagwörter gespeichert). Und diese Tabelle ist dann eine dritte Tabelle, in der bei jedem Datensatz eine Bild ID und eine Schlagwort ID stehen?

            Ja. Verwende am Besten sprechende Namen, also z.B. "Bilder" für die Tabelle mit den Bildern, "Kategorien" für die Tabelle mit den Schlagworten und "Zuordnung" für die Tabelle, welche die Verbindung zwischen den Bildern und den Kategorien herstellt. Dann gibt's weniger Missverständnisse :)

            Nee, mir ist schon klar wie man einen normalen INSERT macht.
            Aber in diesem Fall ist das ja etwas anders.
            Angenommen ein User ordnet einem Bild 5 Schlagwörter zu.
            Dann ergänze ich die dritte Tabelle (Bild_ID, Schlagwort_ID) jeweils um 5 Einträge.

            Willst Du die Schlagwörter nutzerbezogen speichern?

            Aber jetzt habe ich ein Problem:
            Wenn ein User einem Bild ein neues Schlagwort zuordnen will, muss ich erstmal gucken, welche Schlagworte das Bild hat und überprüfen, ob das Schlagwort nicht schon dabei ist.

            Biete dem Nutzer doch einfach bereits verwendete Schlagworte nicht mehr zur Auswahl an, indem Du vor Augabe des Formulars via PHP die aktuell vergebenen Schlagworte abfragst. Wahrscheinlich machst Du doch sowieso eine DB-Abfrage auf die Tabelle "Kategorien", um alle möglichen Schlagworte zu ermitteln, dann selektierst Du nur diejenigen Schlagworte, die in der Tabelle "Zuordnung" zur jeweiligen Bild-ID noch nicht zugeordnet sind (die Links zu den JOIN-Artikeln hast Du ja schon).

            Siechfred

            --
            Hinter den Kulissen passiert viel mehr, als man denkt, aber meistens nicht das, was man denkt.
            1. Hallo,

              Biete dem Nutzer doch einfach bereits verwendete Schlagworte nicht mehr zur Auswahl an,

              ... oder schau Dir mal REPLACE an.

              LG
              Chris©

            2. Ok, soweit klar. Ich habe erst jetzt verstanden, dass ihr mit "Kat" wohl Kategorie also ein Schlagwort meintet. Dann wäre diese Tabelle hier sozusagen eine Liste der Schlagworte.

              Genau.

              Jetzt möchtest Du aus der Tabelle "Bilder" diese zwei Kategorien dem Bild mit der Nummer 3 zuordnen. Dann sähe Deine 2. Tabelle so aus: [...]
              Stopp mal, welche Tabelle ist das jetzt? Wir haben ja nun Tabelle1 (da sind alle Bilder gespeichert, inkl. Auflösung) und Tabelle2 (da sind alle Schlagwörter gespeichert). Und diese Tabelle ist dann eine dritte Tabelle, in der bei jedem Datensatz eine Bild ID und eine Schlagwort ID stehen?

              Ja. Verwende am Besten sprechende Namen, also z.B. "Bilder" für die Tabelle mit den Bildern, "Kategorien" für die Tabelle mit den Schlagworten und "Zuordnung" für die Tabelle, welche die Verbindung zwischen den Bildern und den Kategorien herstellt. Dann gibt's weniger Missverständnisse :)

              Wie würde ich denn die Zuordnungstabelle im richtigen Einsatz nennen? Einfach Zuordnung wäre blöde, eher soetwas wie Zuordnung_Bilder-Schlagworte, bzw. auf Englisch. Was wäre da gut?

              Nee, mir ist schon klar wie man einen normalen INSERT macht.
              Aber in diesem Fall ist das ja etwas anders.
              Angenommen ein User ordnet einem Bild 5 Schlagwörter zu.
              Dann ergänze ich die dritte Tabelle (Bild_ID, Schlagwort_ID) jeweils um 5 Einträge.

              Willst Du die Schlagwörter nutzerbezogen speichern?

              Nein, aber die Nutzer selbst entscheiden darüber, welches Bild welche Schlagworter bekommt. Daher... (s.u.)

              Aber jetzt habe ich ein Problem:
              Wenn ein User einem Bild ein neues Schlagwort zuordnen will, muss ich erstmal gucken, welche Schlagworte das Bild hat und überprüfen, ob das Schlagwort nicht schon dabei ist.

              Biete dem Nutzer doch einfach bereits verwendete Schlagworte nicht mehr zur Auswahl an, indem Du vor Augabe des Formulars via PHP die aktuell vergebenen Schlagworte abfragst.

              ...geht das so nicht. Die Nutzer müssen sowohl die Möglichkeit haben, bereits bestehende Schlagworte zu löschen, neue Schlagworte zu erfinden und bereits vorhandene Schlagwort zu ändern (zu korrigieren). Ein Nutzer sieht also ein Bild mit fünf Schlagworten. Er kann selbst ein neues Schlagwort hinzufügen (sich frei ausdenken). Gibt es dieses noch nicht, wird es in die Schlagworttabelle übernommen. Sieht er aber ein falsch geschriebenes Schlagwort, soll er dieses auch korrigieren können. Es müssen also alle vorhandenen Schlagwörter angezeigt werden und beim Speichern müssen alle Schlagworte überprüft werden. Das könnte ziemlich aufwendig sein.

              Für das Ersetzen werde ich wohl den Vorschlag von Chris (REPLACE) nehmen, das ist für das Problem des Hinzufügens neuer Schlagwörter genau das richtige. Trotzdem habe ich immernoch Performancebedenken.

              1. Hallo John,

                Für das Ersetzen werde ich wohl den Vorschlag von Chris (REPLACE) nehmen, das ist für das Problem des Hinzufügens neuer Schlagwörter genau das richtige. Trotzdem habe ich immernoch Performancebedenken.

                weshalb? Solche Zuordnungstabellen sind einfach und durchaus performant. Suche in irgendwelchen Arrays bzw. Zeichenketten überhaupt nicht, lies Dir bitte dazu  folgenden aktuellen Thread durch - und stell' Dir vor, die dortigen Zahlen in der Monsterabfrage wären Schlagworte.

                Freundliche Grüße

                Vinzenz

  3. Nochmal etwas ganz anderes.

    Ist es überhaupt gut, die Bilder in einer Datenbank zu speichern, oder wäre es aus Performancegründen besser, nur den Link zum Bild selbst zu speichern, welches dann als Datei gespeichert ist?

    1. Hi,

      Ist es überhaupt gut, die Bilder in einer Datenbank zu speichern,

      In aller Regel: Nein.

      oder wäre es aus Performancegründen besser, nur den Link zum Bild selbst zu speichern, welches dann als Datei gespeichert ist?

      Ja.
      Das Dateisystem ist der bessere Ablageort fuer grosse Binaerdateien.

      MfG ChrisB

      1. Hallo,

        Ist es überhaupt gut, die Bilder in einer Datenbank zu speichern,

        In aller Regel: Nein.

        Imho kommt das auf die Größe der Bilder an. Tausende von kleinen und kleinsten Bildern sind besser IN der Datenbank aufgehoben, als "lose" auf der Platte, wo dann vielleicht für jedse 200Bytes große Icon 8kBytes oder mehr verballert werden.

        Große Bilder belasten dann allerdings die Datenbank und ihre Datenpuffer unangemessen.

        LG
        Chris©

        1. Hallo,

          Ist es überhaupt gut, die Bilder in einer Datenbank zu speichern,

          In aller Regel: Nein.

          Imho kommt das auf die Größe der Bilder an. Tausende von kleinen und kleinsten Bildern sind besser IN der Datenbank aufgehoben, als "lose" auf der Platte, wo dann vielleicht für jedse 200Bytes große Icon 8kBytes oder mehr verballert werden.

          Ach herrje, der Arme =/

          Wäre dann vielleicht jemand anders so nett, mir eine Antwort auf meine Frage zu Toms Hilfe zu geben? (http://forum.de.selfhtml.org/?t=168340&m=1098358)

          1. Hi,

            Wäre dann vielleicht jemand anders so nett, mir eine Antwort auf meine Frage zu Toms Hilfe zu geben? (http://forum.de.selfhtml.org/?t=168340&m=1098358)

            Moeglich - draengeln brauchst du deswegen aber nicht.

            MfG ChrisB