SQLite und Encoding

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?

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

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

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.

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

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

Deshalb mein Encoding isolatin1, womit es korrekt funktioniert.

Komisch

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

Wahrscheinlich mache ich irgendwas falsch…

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?

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?

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

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 @Sascha S von übernächsten Beitrag eingefügt)

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

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

db.SQLExecute("Set names UTF8")

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

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

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

Wert holen

[code]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”)[/code]

Wert schreiben

[code]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
[/code]

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!