SQLite und Encoding

  1. 4 weeks ago

    Tim W

    Oct 16 Pre-Release Testers Solingen, Germany

    Hallo zusammen,
    habe ich es richtig verstanden, dass ich bei einer SQLite Datenbank die Strings mit deutschen Umlauten speichert, diese in BLOBs speichern muss, da es keine Möglichkeit des Encodings gibt?

    Also... meine Vermutung:
    die Werte in der DB wurden als "ISOLatin1" gesendet, aber als "ISOLatin1-im-UTF8-Kleid" gespeichert (da das Encoding für die Verbindung UTF8 ist). Die DB meint also UTF8 zu erhalten (erhält aber effektiv ein "Bag-of-Bytes" im ISOLatin1-Format).
    Daher erhält man mit rs.field("einheit").stringvalue ein ISOLatin1-String zurück (aber definiert als UTF8, von der DB-Verbindung her). Daher muss das jetzt explizit wieder als ISOLatin1 zurück-definiert werden mit rs.field("einheit").stringvalue.defineencoding(encodings.isolatin1) (damit erhält man das zurück, was vorher "falsch" gespeichert wurde).
    Das Problem ist also, dass die DB UTF8 zu haben meint - aber effektiv wurden darin ISOLatin1-Werte gespeichert...?

    Ganz allgemein funktioniert folgendes eigentlich zu 100%:

    • Encoding/Schema der DB ist auf UTF8 definiert
    • Nach Verbindungsaufbau sicherstellen, dass die Verbindung mit UTF8 genutzt wird. Im Falle von MySQL: DB.SQLExecute("SET NAMES 'utf8';"), dann noch DB.SQLExecute("SET CHARACTER_SET 'utf8';")
    • Speichern von Werten: sicherstellen, dass man UTF8 sendet ConvertEncoding("meinWert", Encodings.UTF8)
    • Abholen von Werten: sicherstellen, dass man das erwartete Encoding definiert (an sich unnötig, aber irgendwie doch empfehlenswert): rs.field("einheit").stringvalue.defineencoding(Encodings.UTF8)

    (edit: den Hinweis von @SaschaSchneppmueller von übernächsten Beitrag eingefügt)

  2. Carsten B

    Oct 16 Pre-Release Testers, Xojo Pro Germany, NRW, Europe

    Hallo Tim, da hast Du wohl was falsch verstanden; SQLite ist standardmäßig auf UTF8 eingestellt, speichert also Umlaute und alle anderen Sonderzeichen.

  3. Markus R

    Oct 16 Pre-Release Testers, Xojo Pro Europe / Germany

    BLOBs sind für binär Daten wie Dateien oder kleinere Bilder also Bytes ..

  4. Tim W

    Oct 16 Pre-Release Testers Solingen, Germany

    Jetzt bin ich etwas verwirrt....
    Ich benutze stets isolatin1 als encoding, auch für meine MySQL-Datenbank, da ich mit utf8 keine Sonderzeichen korrekt dargestellt bekomme. Da ich in den XOJO-Docs gelesen habe, dass SQLite stets in UTF8 konvertiert und ich andernfalls im BLOB speichern solle, habe ich dies auch so gemacht.
    Nur so werden bei mir die Umlaute auch korrekt ausgelesen und gespeichert.
    Wie gesagt, das gleiche auch in meiner MySQL-DB.

  5. Markus R

    Oct 16 Pre-Release Testers, Xojo Pro Europe / Germany

    In der heutigen Zeit würde ich alles einheitlich auf UTF8 umstellen.
    Kann deine MySQL Version etwa kein UTF8?

  6. Tim W

    Oct 16 Pre-Release Testers Solingen, Germany

    Doch die MySQL ist standardmäßig auch auf UTF8, jedoch bekomme ich in Xojo die Umlaute/Sonderzeichen nicht korrekt dargestellt und gespeichert.

  7. Tim W

    Oct 16 Pre-Release Testers Solingen, Germany

    Deshalb mein Encoding isolatin1, womit es korrekt funktioniert.

  8. Markus R

    Oct 16 Pre-Release Testers, Xojo Pro Europe / Germany

    @Tim W Doch die MySQL ist standardmäßig auch auf UTF8, jedoch bekomme ich in Xojo die Umlaute/Sonderzeichen nicht korrekt dargestellt und gespeichert.

    Komisch

  9. Tim W

    Oct 16 Pre-Release Testers Solingen, Germany

    Das hat mich schon immer irritiert, dass ich in XOJO ein anderes Encoding verwenden muss, als meine mySQL hat

  10. Tim W

    Oct 16 Pre-Release Testers Solingen, Germany

    Wahrscheinlich mache ich irgendwas falsch...

  11. Markus R

    Oct 16 Pre-Release Testers, Xojo Pro Europe / Germany

    Hast du auch schon Xojo 2019r2?
    MySQL habe ich zu Hause installiert.
    Kann ich ja mal testen mit Umlaute und so.
    Du sprichst von einer Desktop Anwendung ja?

  12. Tim W

    Oct 16 Pre-Release Testers Solingen, Germany

    Hallo Markus,
    Ich arbeite noch mit der 2017 r3. War aber schon immer bei mir so, in allen Versionen.
    Habe es gerade nochmal aktuell probiert. By SQLite, wie auch bei mySQL werden die Umlaute und Sonderzeichen nicht korrekt gelesen und geschrieben.

    Hier mal ein Beispiel wie ich zugreife bzw. speicher (ist in diesem Fall die SQLite)

    Dim sql As String
    Dim rs As RecordSet
    sql="SELECT einheitNr, einheit, einheitlang FROM core_artikeleinheiten WHERE sprache="+Str(currUser.Sprache)+";"
    rs=DBCore.SQLSelect(sql)
    If DBCore.Error=True Then
      Dim aktdat As  New date
      fehlertexte.Append(aktdat.ShortDate+" "+aktdat.LongTime+": Fehler "+Str(DBCore.ErrorCode)+" "+DBCore.ErrorMessage)
    End If
    If rs<>Nil Then
      While Not rs.EOF
        dAEinheiten.value(rs.Field("einheitNr").IntegerValue)=rs.Field("einheit").StringValue
        dAEinheitenLang.Value(rs.Field("einheitNr").IntegerValue)=rs.Field("einheitLang").StringValue
        rs.MoveNext
      Wend
    End If

    Das gleiche gilt für den Zugriff auf die mySQL, es sei denn ich definiere das encoding, also z. B.:

    rs.field("einheit").stringvalue.defineencoding(encodings.isolatin1) -> dann funktioniert es

    Mache ich da was falsch?

  13. Tim W

    Oct 16 Pre-Release Testers Solingen, Germany

    Das mit dem encoding funktioniert übrigens nicht bei der SQLite, hier werden die Umlaute immer noch als Rauten dargestellt

  14. Jürg O

    Oct 16 Pre-Release Testers, Xojo Pro Answer
    Edited 4 weeks ago

    Also... meine Vermutung:
    die Werte in der DB wurden als "ISOLatin1" gesendet, aber als "ISOLatin1-im-UTF8-Kleid" gespeichert (da das Encoding für die Verbindung UTF8 ist). Die DB meint also UTF8 zu erhalten (erhält aber effektiv ein "Bag-of-Bytes" im ISOLatin1-Format).
    Daher erhält man mit rs.field("einheit").stringvalue ein ISOLatin1-String zurück (aber definiert als UTF8, von der DB-Verbindung her). Daher muss das jetzt explizit wieder als ISOLatin1 zurück-definiert werden mit rs.field("einheit").stringvalue.defineencoding(encodings.isolatin1) (damit erhält man das zurück, was vorher "falsch" gespeichert wurde).
    Das Problem ist also, dass die DB UTF8 zu haben meint - aber effektiv wurden darin ISOLatin1-Werte gespeichert...?

    Ganz allgemein funktioniert folgendes eigentlich zu 100%:

    • Encoding/Schema der DB ist auf UTF8 definiert
    • Nach Verbindungsaufbau sicherstellen, dass die Verbindung mit UTF8 genutzt wird. Im Falle von MySQL: DB.SQLExecute("SET NAMES 'utf8';"), dann noch DB.SQLExecute("SET CHARACTER_SET 'utf8';")
    • Speichern von Werten: sicherstellen, dass man UTF8 sendet ConvertEncoding("meinWert", Encodings.UTF8)
    • Abholen von Werten: sicherstellen, dass man das erwartete Encoding definiert (an sich unnötig, aber irgendwie doch empfehlenswert): rs.field("einheit").stringvalue.defineencoding(Encodings.UTF8)

    (edit: den Hinweis von @SaschaSchneppmueller von übernächsten Beitrag eingefügt)

  15. Tim W

    Oct 16 Pre-Release Testers Solingen, Germany

    Hallo Jürg, erstmal vielen Dank.
    Das ist eine gute Analyse und Idee. Werde ich mich gleich mal dran probieren.

  16. Sascha S

    Oct 16 Pre-Release Testers, Xojo Pro Germany, Lower Saxonary
    Edited 4 weeks ago

    @Tim W Ich benutze stets isolatin1 als encoding, auch für meine MySQL-Datenbank, da ich mit utf8 keine Sonderzeichen korrekt dargestellt bekomme.

    Was passiert wenn Du direkt nach dem Connect zu DB folgenden Querrie an die DB sendest?

    db.SQLExecute("Set names UTF8")
  17. Jürg O

    Oct 16 Pre-Release Testers, Xojo Pro

    @SaschaSchneppmueller direkt nach dem Connect zu DB folgenden Querrie an die DB sendest

    Stimmt - danke für den Hinweis. Das habe ich oben noch eingefügt (und ergänzt mit SET CHARACTER_SET 'utf8')

  18. Tim W

    Oct 16 Pre-Release Testers Solingen, Germany

    Super...das scheint nun zu funktionieren. Vielen Dank an Alle für die Hilfen.

  19. Markus R

    Oct 16 Pre-Release Testers, Xojo Pro Europe / Germany

    also bei 2019r2 keine Probleme mit sqlite und Umlaute
    habe zum testen einfach zwei Knöppe und eine Textbox benutzt.

    Wert holen

    Dim db As New SQLiteDatabase
    db.DatabaseFile = SpecialFolder.Documents.Child("database.sqlite")
    db.connect
    
    Dim rs As RecordSet
    Dim sql As String = "SELECT Id,Untitled1 FROM Test WHERE Id = 1;"
    rs = db.SQLSelect(sql)
    TextField1.Text = rs.Field("Untitled1")

    Wert schreiben

    Dim db As New SQLiteDatabase
    db.DatabaseFile = SpecialFolder.Documents.Child("database.sqlite")
    db.connect
    
    Dim rs As RecordSet
    Dim sql As String = "SELECT Id,Untitled1 FROM Test WHERE Id = 1;"
    rs = db.SQLSelect(sql)
    rs.Edit
    rs.Field("Untitled1").StringValue = TextField1.Text
    rs.Update
  20. Tim W

    Oct 16 Pre-Release Testers Solingen, Germany

    Ich bin echt happy! Mit dem Encoding funktioniert nun alles super. Der entscheidende Hinweis war die Tatsache, dass nicht nur das Encoding der Tabellen entscheidend ist, sondern auch die Verbindung das Encoding haben muss.

    Ich habe mich wirklich schon Jahre mit dem Encoding herumgeschlagen und jetzt endlich richtig verstanden! Danke nochmals an Alle!

or Sign Up to reply!