Steffen: Eintrag in mysql Datenbank behandeln

Moin,

wenn ich einen Eintrag in meine mysql-db vornehme, behandel ich ihn normalerweise mit mysqli_real_escape_string($sql,trim($string)).

Ist das richtig so?

Ich frag, weil ich immer wieder Probleme habe mit Strings, die Anführungszeichen enthalten. Da wird schonmal aus

Verbinder kpl. 3/8"

nach dem Excel daraus eine CSV-Datei macht:

"Verbinder kpl. 3/8"""

und dann nach dem db-Eintrag:

\"Verbinder kpl. 3/8\"\"\"

Ich weiß gar nicht, wo ich hier ansetzen soll. Kann mir das einer sagen?

Mein 2. Problem ist:

Ich sammel Bemerkungen zu einem Artikel in einem Array. Anschließend möchte ich die Bemerkungen zeilengetrennt in die Spalte (text) übernehmen.

$eintragBemerkung = implode('\n',$Bemerkung);
$eintragBemerkung = mysqli_real_escape_string($sql,trim($eintragBemerkung))

Heraus kommt:

D10\nlieferbar

Was mache ich denn da falsch?

VG, Steffen

  1. Hallo

    wenn ich einen Eintrag in meine mysql-db vornehme, behandel ich ihn normalerweise mit mysqli_real_escape_string($sql,trim($string)).

    Ist das richtig so?

    Wenn in $string ein String steckt, ja.

    Ich frag, weil ich immer wieder Probleme habe mit Strings, die Anführungszeichen enthalten. Da wird schonmal aus

    Verbinder kpl. 3/8"
    

    nach dem Excel daraus eine CSV-Datei macht:

    "Verbinder kpl. 3/8"""
    

    Soweit, so normal. Du benutzt als Zollzeichen das doppelte Anführungszeichen und jenes wird in einem String, der in CSV in doppelten Anführungszeichen eingeschlossen ist, mit einem weiteren doppelten Anführungszeichen maskiert. Typografisch korrekt ist das nicht und mit dem richtigen Zeichen – laut Wikipedia dieses hier: – würde dieses Problem nicht bestehen.

    und dann nach dem db-Eintrag:

    \"Verbinder kpl. 3/8\"\"\"
    

    Ab hier wird's komisch. Mit einer Funktion, die CSV im verarbeitenden Programm in Variablen importiert, sollten erstens die den String einschließenden doppelten Anführungszeichen entfernt werden und zweitens die Maskierung aufgehoben werden. Da du offensichtlich PHP benutzt, wäre das die Funktion fgetcsv. Es würde dann das herauskommen:

    Verbinder kpl. 3/8"
    

    Wird dieser String mit mysqli_real_escape_string behandelt, stünde auch genau dieser String in der Datenbank.

    Tschö, Auge

    --
    200 ist das neue 35.
    1. Typografisch korrekt ist das nicht und mit dem richtigen Zeichen – laut Wikipedia dieses hier: – würde dieses Problem nicht bestehen.

      Leider habe ich darauf keinen Einfluss. Die Daten kommen von extern.

      Steffen

      1. Hallo Steffen,

        Leider habe ich darauf keinen Einfluss. Die Daten kommen von extern.

        Einfluss hast Du nur darauf, wie Du die Daten aus der CSV Datei einliest. Zerlegst Du den String "von Hand"? Oder nutzt Du fgetcsv bzw. str_getcsv? Die nehmen Dir das ab und sind standardisiert.

        Guck hier:

        <?php
        $a = <<<END
        Das ist Test,Verbinder 3/8","Verbinder 3/8"""
        END;
        
        $b = str_getcsv($a);
        print_r($b);
        
        Array
        (
            [0] => Das ist Test
            [1] => Verbinder 3/8"
            [2] => Verbinder 3/8"
        )
        

        Rolf

        --
        sumpsi - posui - obstruxi
        1. Hallo Rolf,

          Leider habe ich darauf keinen Einfluss. Die Daten kommen von extern.

          Einfluss hast Du nur darauf, wie Du die Daten aus der CSV Datei einliest. Zerlegst Du den String "von Hand"? Oder nutzt Du fgetcsv bzw. str_getcsv? Die nehmen Dir das ab und sind standardisiert.

          gut und schön, aber CSV wird so vielfältig interpretiert, dass man mit einer "streng nach Standard" gemachten Routine oft nicht glücklich wird:

          • Stehen Strings konsequent in Anführungszeichen? Sollten sie eigentlich, ist aber nicht immer der Fall.
          • Welches Zeichen wird als Feld-Delimiter verwendet? Die Bezeichnung CSV stand ursprünglich mal für "Comma Separated Values", aber heute wird auch gern ein Semikolon, ein Doppelpunkt oder ein Tabulator genommen.
          • Werden Delimiter innerhalb der Felder konsequent maskiert? Also vor allem Anführungszeichen innerhalb von Strings?
          • Wie werden Steuerzeichen dargestellt (z.B. Zeilenumbrüche)? Stehen sie verbatim im CSV-Code, werden sie als C-Escape-Sequenzen notiert?

          Man kommt dabei immer zum gleichen Fazit: Wenn man sich auf einen bestimmten CSV-Dialekt einstellt, oder beispielsweise fgetcsv() unfallfrei mit den Quelldaten arbeiten kann, ist das schön. Ein universelles Austauschformat ist das aber nicht.

          Einen schönen Tag noch
           Martin

          --
          Was ist der schnellste Weg von einem Suchtreffer zum nächsten?
          Ein Googlehupf.
          1. Hallo Martin,

            da hast Du natürlich recht - CSV ist ein Unfall, der darauf wartet, zu passieren. Bloß - Excel ist das Lieblingsspielzeug aller Bürohengste (und -stuten) und wenn die Daten dort stehen, gibt es kaum eine andere Wahl.

            Ich habe jetzt nochmal mit einer CSV Datei statt einem String experimentiert - die Zeilenumbrüche funktionieren nicht gut. Weil EXCEL einen Zeilenumbruch in einer Zelle als \n speichert - das CSV Zeilenende dann als \r\n. Und ich kriege PHP nicht beigebracht, Zeilen ausschließlich bei CR+LF zu beenden. Geht das nicht?!

            Mit file_get_contents und explode auf \r\n, dann ein str_getcsv auf die Fragmente geht es. Brrr. Solange die CSV Datei nicht zu groß ist... Aber die Datei zeichenweise mit fgetc einlesen und die Zeilenenden selbst zu erkennen dürfte bei großen Dateien nicht praktikabel sein.

            Edit: Autsch - geht doch. Keine Ahnung was ich da eben verbockt habe. Zeilenumbrüche in einer Zelle, die in Anführungszeichen in der CSV steht, werden von fgetcsv ordentlich verarbeitet. Das war in alten PHP Versionen mal falsch.

            Rolf

            --
            sumpsi - posui - obstruxi
            1. Hallo,

              da hast Du natürlich recht - CSV ist ein Unfall, der darauf wartet, zu passieren.

              sehr treffend formuliert. Also im Prinzip ähnlich wie TIFF im Bereich Grafikformate: Es gibt wohl einen Standard, aber der ist so schwammig und lässt viele Freiheiten, dass die Aussage "Programm foo kann TIFF-Dateien verarbeiten" nur unter streng kontrollierten Laborbedingungen verifizierbar ist.

              Bloß - Excel ist das Lieblingsspielzeug aller Bürohengste (und -stuten) und wenn die Daten dort stehen, gibt es kaum eine andere Wahl.

              Ich weiß. Als Ingenieur weiß ich Excel auch zu schätzen, bin dann aber auch immer wieder enttäuscht, wenn es an scheinbar selbstverständlichen Anforderungen scheitert.

              Da hatte ich vor einiger Zeit eine Excel-Tabelle mit einem Messprotokoll: Spalte A war der Timestamp, Spalten B und C je ein Messwert, und in Spalte D sporadisch ein Kommentar zum Messwert (sowas wie "Einschaltstrom", "vermutlich Fehlmessung" oder "Sicherung hat ausgelöst").

              Ich wollte daraus ein Diagramm erzeugen. Timestamp auf der X-Achse, die zwei Messwerte als zwei Kurven, und den Kommentar aus Spalte D als Text im Diagramm mit Marker an der passenden Stelle. Letzteres habe ich nicht geschafft. Im besten Fall kannst du von Hand Texte, Linien oder Marker ins fertige Diagramm malen. Die folgen dann aber natürlich nicht einer veränderten Skalierung oder so.

              Ich habe jetzt nochmal mit einer CSV Datei statt einem String experimentiert - die Zeilenumbrüche funktionieren nicht gut. Weil EXCEL einen Zeilenumbruch in einer Zelle als \n speichert - das CSV Zeilenende dann als \r\n. Und ich kriege PHP nicht beigebracht, Zeilen ausschließlich bei CR+LF zu beenden. Geht das nicht?!

              Nein, ich glaube nicht. Meines Wissens hat PHP da eine gewisse Pseudo-Intelligenz, die Zeilenumbrüche verschiedener Plattformen (Windows \r\n, Unixoide \n, ältere Äpfel \r) als gleichwertig zu erkennen.

              Mit file_get_contents und explode auf \r\n, dann ein str_getcsv auf die Fragmente geht es. Brrr. Solange die CSV Datei nicht zu groß ist... Aber die Datei zeichenweise mit fgetc einlesen und die Zeilenenden selbst zu erkennen dürfte bei großen Dateien nicht praktikabel sein.

              Ja, die Variante wäre mir auch eingefallen. Oder die Datei zeichenweise lesen und Zeichen sammeln bis zum \r\n, einzeln auftretende \n dabei einfach als Nutzzeichen durchreichen. Dürfte deutlich langsamer sein, aber wenig Speicher brauchen.

              Einen schönen Tag noch
               Martin

              --
              Was ist der schnellste Weg von einem Suchtreffer zum nächsten?
              Ein Googlehupf.
  2. Hallo Steffen,

    Das CSV Problem ist kein Problem der Datenbank. Wenn du CSV einliest, musst du die Maskierungen darin entfernen, bevor du die Daten weiterverarbeitest.

    Dass aus dem Zeilenumbruch ein \n wird, scheint mir erstmal korrekt. Ich kann das allerdings im Moment nicht durchprobieren. Was kommt denn im Browser an, wenn du den Wert wieder einliest und ausgibst?

    Ah, Moment, da steht '\n'. Nimm "\n". Sonst macht PHP kein Steuerzeichen daraus.

    Rolf

    --
    sumpsi - posui - obstruxi
    1. Hallo Rolf,

      Ah, Moment, da steht '\n'. Nimm "\n". Sonst macht PHP kein Steuerzeichen daraus.

      Ok, das klingt einleuchtend.

      Steffen

  3. Moin Steffen,

    wenn ich einen Eintrag in meine mysql-db vornehme, behandel ich ihn normalerweise mit mysqli_real_escape_string($sql,trim($string)).

    Ist das richtig so?

    Wenn du keine Prepared Statements verwenden möchtest, ja.

    Ich frag, weil ich immer wieder Probleme habe mit Strings, die Anführungszeichen enthalten. Da wird schonmal aus

    Verbinder kpl. 3/8"
    

    nach dem Excel daraus eine CSV-Datei macht:

    "Verbinder kpl. 3/8"""
    

    Das ist korrekt maskiert für den Kontextwechsel nach CSV.

    und dann nach dem db-Eintrag:

    \"Verbinder kpl. 3/8\"\"\"
    

    Steht das so in der Datenbank? Hast du eventuell irgendwo magic quotes in Kombination mit dem fehlenden Decodieren aus dem CSV-Kontext?

    Mein 2. Problem ist:

    Ich sammel Bemerkungen zu einem Artikel in einem Array. Anschließend möchte ich die Bemerkungen zeilengetrennt in die Spalte (text) übernehmen.

    $eintragBemerkung = implode('\n',$Bemerkung);
    $eintragBemerkung = mysqli_real_escape_string($sql,trim($eintragBemerkung))
    

    Heraus kommt:

    D10\nlieferbar
    

    Was mache ich denn da falsch?

    '\n' ist etwas Anderes als "\n".

    Viele Grüße
    Robert

    1. Hi Robert,

      Verbinder kpl. 3/8"
      

      nach dem Excel daraus eine CSV-Datei macht:

      "Verbinder kpl. 3/8"""
      

      Das ist korrekt maskiert für den Kontextwechsel nach CSV.

      Habe jetzt Openoffice benutzt, da wird das nicht gemacht.

      Steht das so in der Datenbank? Hast du eventuell irgendwo magic quotes in Kombination mit dem fehlenden Decodieren aus dem CSV-Kontext?

      Müsst ich nachsehen, glaubs aber nicht.

      '\n' ist etwas Anderes als "\n".

      Danke, wieder was gelernt.

      Steffen