FB 3.0: Problem beim Daten-Pumpen von ISO-8859-1 auf UTF8

Themen rund um den praktischen Einsatz von Firebird. Fragen zu SQL, Performance, Datenbankstrukturen, etc.

Moderator: thorben.braun

Hamburgo
Beiträge: 125
Registriert: Di 28. Mai 2019, 17:28

Wie erklärt sich, wenn ich Daten Feld für Feld, z.B. eine PLZ von einer ISO-8859-1-DB in eine
UTF8-DB pumpe, der Feld-Wert eine Länge von 20 hat und nach den 5 Ziffern 15 Leerzeichen
enthält, obwohl die Domain für das Feld in beiden DBs identisch ist.

z.B.: DOMAIN "SC5" AS CHAR(5);

510. plz (CHAR) Alt: (5) >64342< | Neu: (20) >64342###############<

Die Rauten (#) dienen nur der Sichtbar-Machung der Leerzeichen - ord=32

Wenn ich die Parameter des Feldes aus FB auslese, dann steht da für das Feld PLZ eine länge von 20 und nicht 5, wie in der Domain vorgegeben.

Liegt es evtl. daran, dass ích die Meta-Daten per FB-SQL in die nackte UTF8-DB eingetragen habe und nicht manuell (war mir zuviel Aufwand) über einen DB-Manager (z.B. IB-Expert).

Danke und Grüße
Hamburgo
bfuerchau
Beiträge: 485
Registriert: Mo 7. Mai 2018, 18:09
Kontaktdaten:

Ganz einfach: char(n) ist ein Feld fixer Länge und wird mit Leerzeichen aufgefüllt. Dies war schon immer so. Klar, bei einer 5-Stelligen Zahl in einem 5-stelligen Feld merkt man das nicht.
Was du willst ist ein VARCHAR(20). Dann entält es genau so viele Zeichen wie du übergibst: "ABCD", "ABCD#", ABCD####".
Das Gemeine an diesen Daten ist, dass der SQL-Vergleich (Suche allgemein) Leerzeichen am Ende nicht berücksichtigt.
Wenn du nun aber beim Lesen der Daten die Endeleerzeichen nicht entfernst (TrimEnd), so sind die Werte im Programmvergleich nicht identisch.

Ich kenne nur VBA, wo man das per "option compare database" eben auf SQL-Vergleiche umstellen kann.
Hamburgo
Beiträge: 125
Registriert: Di 28. Mai 2019, 17:28

Das char(n) Felder mit fixer Länge sind, ist mir schon bekannt.

Soweit ich es bisher überblicken kann, habe ich dieses Problem primär mit Feldern,
welche der von mir definierten Domain "SC5" zugeordnet sind, egal in welcher Tabelle !

DOMAIN "SC5" AS CHAR(5);

In diesen Feldern werden ausschließlich PLZ's und Zeitwerte in der Form SS:MM gespeichert.

Alle Domain's wurden VOR dem Daten-Pumpen eingetragen, so auch die SC5.

Das anhängende Bild zeigt z.B. die Tabelle Jobs mit den Feldern BEGINN_MA, SCHLUSS_MA,
BEGINN_BELEG und SCHLUSS_BELEG in IBExpert.

Die Domain "SC5" ist korrekt zugeordnet und die Feldlänge wird von IBExpert mit 5 angezeigt und bei einem Eingabe-Versuch wirft er einen Fehler, wenn ich mehr als 5 Zeichen erfassen will,
real gespeichert sind aber die gepumten Daten mit einer fixen Länge 20, also der Zeitwert zzgl. 15 Blanks und auch in der FB-System-Tabelle sind die Felder mit der fixen Länge 20 statt 5 eingetragen.

12345123456789-12345
2507. beginn_ma (CHAR-20) Alt: (5) >11:00< | Neu: (20) >11:00###############<

Diese Zeile zeigt am Beispiel des Feldes beginn_ma den Wert aus der Alt-DB und den
Wert aus der Neu-DB.

Was läuft da schief ?
Dateianhänge
TDL-Jobs01.png
TDL-Jobs01.png (74.92 KiB) 10468 mal betrachtet
bfuerchau
Beiträge: 485
Registriert: Mo 7. Mai 2018, 18:09
Kontaktdaten:

Womit schaust du dir an, ob die Domain auch wirklich so dem Feld zugeordnet ist?
Schau u.U. mal in die RDB$FIELDS genau rein.
Hamburgo
Beiträge: 125
Registriert: Di 28. Mai 2019, 17:28

Meine Kenntnisse um in die System-Tabellen von FB reinzuschauen
bewegen sich nahezu gen null.

Weder kenne ich genau die Struktur, noch weiss ich wo was steht.

Um meine DBs zu managen nutze ich in der Regel IBexpert und vertraue darauf,
dass diese die System-Tabellen vom FB korrekt beschicken.

Einzig jetzt für die Migrierung von FB 2.5 ISO-8859-1 auf FB 3.0 UTF8 habe ich
die Create-Befehle per SQL-Statements in die DB eingetragen.

Aber auch dafür habe ich die Create-Befehle nicht selber zusammen gebaut,
sondern aus dem DLL-Fenster vom DB-Manager in mein Script kopiert.

Da vertraue ich voll der Expertise der Fachleute von IBexpert, was auch
seit Jahren innerhalb von FB 2.5 ISO-8859-1 hervorragend geklappt hat.

Soweit ich es bisher überblicken kann, hat es ja jetzt auch für FB 3.0 UTF8
fast vollständig geklappt, ausser bei dieser speziellen Domain "SC5" nicht.
bfuerchau
Beiträge: 485
Registriert: Mo 7. Mai 2018, 18:09
Kontaktdaten:

Ok, jetzt komme ich dahinter.
Wenn du die Daten nun mit UTF8 in der Verbindung ausliest, erhältst du nun auch ein Feld mit 5 Zeichen * 4 Bytes macht 20 Zeichen.
Da aber UTF8 ein variabler Zeichensatz ist, kann das mit CHAR(n) nicht funktionieren sondern muss auf VARCHAR(n) umgestellt werden.

Da nun mal PLZ's sich bei uns nur im normalen Zeichensatz bewegen, wird bei einem CHAR(5) in UTF8 die 20 Bytes mit Leerzeichen aufgefüllt.

Dies wird durchaus alle deine CHAR-Felder betreffen. Stelle diese beim Create Domain auf VARCHAR um.

Je nach Treiber, ich nehme da ODBC bei C++ und .Net bei C# erfolgt die Umwandlung von Feldern zwischen UTF8 und String (also Unicode) automatisch. In der Verbindungsfolge zur FB gebe ich ebenso "CHARSET=UTF8;" an.
Bei anderen Libs (PHP ö.ä.) kann ich nichts zu sagen.
Benutzeravatar
martin.koeditz
Beiträge: 443
Registriert: Sa 31. Mär 2018, 14:35

Hallo bfuerchau,
Wenn du die Daten nun mit UTF8 in der Verbindung ausliest, erhältst du nun auch ein Feld mit 5 Zeichen * 4 Bytes macht 20 Zeichen.
Meintest du hier nicht 20 Bytes? Die Zeichenzahl bleibt ja die gleiche, abhängig vom Zeichensatz verändert sich die Speichermenge.
Je nach Treiber, ich nehme da ODBC bei C++ und .Net bei C# erfolgt die Umwandlung von Feldern zwischen UTF8 und String (also Unicode) automatisch. In der Verbindungsfolge zur FB gebe ich ebenso "CHARSET=UTF8;" an.
Bei anderen Libs (PHP ö.ä.) kann ich nichts zu sagen.
Das ist bei PHP, etc. genauso. Wichtig ist, dass der Zeichensatz der Verbindungsfolge zu dem der DB passt, sonst gibt es nur Kauderwelsch zurück.

Gruß
Martin
Martin Köditz
it & synergy GmbH
Hamburgo
Beiträge: 125
Registriert: Di 28. Mai 2019, 17:28

Hallo Martin,

genau in diese Richtung habe ich gerade auch vergleichbare Erfahrungen
in Tests gemaucht.

Wenn ich ein Feld mit einer Domain CharSet UTF8 verbinde, erhält das Feld
die 4-fache Länge als bei einer Domain z.B. mit CharSet WIN1252.

Viele Grüße
Hamburgo
Hamburgo
Beiträge: 125
Registriert: Di 28. Mai 2019, 17:28

Hallo Martin,

Zitat:
"Wichtig ist, dass der Zeichensatz der Verbindungsfolge zu dem der DB passt,"

Was versteht Ihr unter Verbindungsfolge ?

Danke und Gruss
Hamburgo
bfuerchau
Beiträge: 485
Registriert: Mo 7. Mai 2018, 18:09
Kontaktdaten:

Bei mir ist das der ConnectionString.

Aber trotzdem verhält sich u.U. der Treiber hier falsch, da er auf Grund der CHAR statt Varchar Definition eben immer mit Leerzeichen auffüllt.
Bei ODBC/.Net habe ichda keine Probleme, allerdings nehme ich auch VARCHAR.
Antworten