Diese Notiz beschreibt die operative Ursache von Problemen mit deutschen Umlauten in Informix aus Sicht eines System- oder Datenbankadministrators. Der Schwerpunkt liegt nicht auf der Sprachtheorie, sondern auf den tatsächlichen Betriebsebenen:
Wichtig: In Informix sind Codeset und Collation getrennte Konzepte. Eine falsche Annahme, sie seien identisch oder austauschbar, erzeugt die typischen Umlaut-Fehler.
Informix verwendet GLS (Global Language Support). Eine Locale hat die Form:
Sprache_Territorium.Codeset[@Modifikator]
Typische Beispiele:
Die Bestandteile bedeuten:
Das Entscheidende:
Der Codeset beschreibt, welche Bytes in der Datenbank für ein Zeichen verwendet werden. Beispiel für ISO-8859-1 / IBM CCSID 819:
In UTF-8 dagegen sind dieselben Zeichen mehrere Bytes, beispielsweise:
Das bedeutet: Die logische Rune „ü“ kann in verschiedenen Codesets als unterschiedliche Bytefolge erscheinen. Deshalb ist der tatsächliche Fehler oft ein Encoding-Mismatch, nicht ein Unicode-Problem der Datenbank selbst.
Die Collation beschreibt, wie Zeichen verglichen und sortiert werden. Sie betrifft SQL-Regeln wie:
Ein Modifikator wie @dict ändert nicht das gespeicherte Byte für ü, sondern nur die Reihenfolge, in der Zeichen als vergleichbar bzw. sortierbar behandelt werden.
Praktisch:
Der Ablauf ist immer:
Anwendung → CLIENT_LOCALE → GLS-Konvertierung → DB_LOCALE → Datenseite / Chunk
CLIENT_LOCALE beschreibt die Zeichenkodierung, mit der die Anwendung die Zeichen an den Server sendet. Ein Client kann Latin-1, UTF-8, UCS-2 oder ein anderer von GLS unterstützter Codeset verwenden.
DB_LOCALE beschreibt den Codeset der Datenbank selbst. Sobald die Daten in die Datenbank gelangen, werden sie im DB-Codeset gespeichert. Die Datenbank selbst kennt nur diese interne Byte-Repräsentation.
Wenn Client und Datenbank unterschiedliche Codesets verwenden, führt Informix eine Konvertierung durch. Das ist genau die Stelle, an der viele Fehler entstehen.
Beispiele:
Das ist genau die Ursache, wenn im Feld plötzlich „ü“ oder andere verzerrte Zeichen auftauchen.
Der häufigste Fehler im operativen Umgang ist die falsche Gleichsetzung von Collation und Encoding.
Korrekt:
Falsch:
Diese Annahmen sind technisch falsch.
Beispiel:
Wenn Umlaute in einer Datenbank falsch erscheinen, ist der Fehler in der Regel nicht @dict, sondern:
Informix speichert im Regelfall keine abstrakten „Buchstaben“, sondern Bytefolgen im DB-Codeset. Für 819 gilt:
Wer in einer 819-DB einen Ausdruck wie 'Müller' speichert, speichert in Wirklichkeit eine Bytefolge wie:
Das ist nicht UTF-8, keine kombinierende Darstellung und kein „U+00FC plus Trema“ in einem Zeichensatz-Container. Es ist einfach das DB-Byte.
Das ist der Kernpunkt für Betrieb und Diagnose:
Die Collation beeinflusst nicht die physische Bytefolge, aber sie wirkt auf die Semantik.
Bei 819 ist ein deutsches Zeichen ein einzelnes Byte. Ein Wert wie 'Müller' hat in einer 819-DB eine andere Byte-Länge als in einer UTF-8-DB.
Das ist operational wichtig:
Collation beeinflusst, wie SQL-Engines Zeichen als „gleich“ oder in einer Reihenfolge behandeln. Damit können Werte in WHERE, ORDER BY, BETWEEN und Unique-Prüfungen unterschiedlichen Vergleichsergebnissen unterliegen, obwohl die gespeicherten Bytes identisch sind.
Dieser Effekt ist besonders deutlich bei:
Bei CHAR und VARCHAR richtet sich die normale Vergleichsreihenfolge grundsätzlich nach der Codeset-Reihenfolge; ein in der Locale definierter Modifikator wie @dict kann die Sortierregeln beeinflussen. NCHAR und NVARCHAR verwenden die lokalisierte Kollationsreihenfolge der Datenbank-Locale. Die genaue Wirkung hängt von DB_LOCALE und dessen Collation ab; deshalb sollten Sortierung und Vergleiche mit den tatsächlich verwendeten Datentypen getestet werden.
Je nach Locale und Kollationsregeln können ß und ss beziehungsweise Ä und Ae oder A beim Sortieren ähnlich oder gleich gewichtet werden. Eine ähnliche Sortierposition bedeutet jedoch nicht automatisch, dass die Werte bei = oder in einem Unique-Index als gleich gelten. Diese Fälle separat mit ORDER BY, Gleichheitsvergleichen und gegebenenfalls einem Test-Unique-Index prüfen.
Wenn die Collation zwei Werte als gleich behandelt, kann ein Unique-Index den zweiten Datensatz ablehnen, obwohl die Bytefolgen auf den ersten Blick unterschiedlich aussehen. Das ist ein Kollationsproblem, kein Codepage-Problem.
Dasselbe gilt bei Replikation und ER: Die Vergleichssemantik und die lokale DB-Locale der beteiligten Kataloge und Tabellen müssen für die beteiligten Datenbanken konsistent sein. Eine scheinbar reine Sortierfrage kann sich als Vergleichs-/Katalogproblem zeigen.
Ändert eine logische Migration die Locale oder die zugrunde liegenden Vergleichsregeln, müssen die Indizes in der Zieldatenbank unter diesen Regeln angelegt werden. Vorhandene Indexstrukturen nicht ungeprüft übernehmen: nach dem Import die betroffenen B-Tree-Indizes und Unique-Bedingungen kontrollieren und sie bei Bedarf mit dem für die Informix-Version vorgesehenen Verfahren neu aufbauen, notfalls durch Löschen und erneutes Anlegen. Eine physische Wiederherstellung derselben Datenbank-Locale ist davon zu unterscheiden.
Beispiel: Ein Client sendet UTF-8-C3-BC, der Server erwartet 819, und die Daten werden als zwei falsche Latin-1-Bytes interpretiert. Ergebnis: Zeichen wie ü, ä, ö oder ähnliches.
Typische Ursache:
Wenn UTF-8-Sequenzen in einen 819-Server oder umgekehrt in die falsche Definition geraten, können die Zeichen als ungültig oder unvollständig interpretiert werden. Das führt zu:
Diese Fälle sind häufig ein Kollationsproblem:
Die entscheidende Eigenschaft von Informix-GLS ist: Die Locale der Datenbank, inklusive der Collation, wird beim CREATE DATABASE in die Datenbankstruktur eingepflanzt und bleibt für die Existenz der Datenbank relevant. Das gilt nicht nur für den Sprach-Default, sondern auch für die Vergleichs- und Sortiersemantik der DB.
Das bedeutet praktisch:
Dies ist der Grund, warum eine „Collation-Korrektur“ nachträglich nicht einfach über eine Environment-Variable oder einen einmaligen SET-Block erfolgen kann. Sobald die DB mit einem bestimmten Codeset und einer bestimmten Collation angelegt wurde, ist die physische und semantische Grundlage der Datenbank damit fixiert.
Die häufige falsche Annahme lautet: „Ich ändere DB_LOCALE oder CLIENT_LOCALE und die DB sortiert dann anders.“ Das ist nur für neue Verbindungen und neue Konvertierungen relevant, nicht für die bereits in der Datenbank gespeicherten Bytes und nicht für die bereits definierte DB-Locale.
Das ist ein wichtiger Punkt:
Kurz gesagt: Environment-Variablen sind nur die Konvertierungs- und Verbindungslogik; sie sind keine Definition der bereits gespeicherten DB-Semantik.
Die operative Abhängigkeit ist:
Wenn diese drei Seiten nicht zusammenpassen, ist der Effekt:
Wenn eine DB mit dem falschen Codeset oder falscher Collation erstellt wurde, dann ist das Problem nachträglich nicht nur eine Frage der aktuellen Umgebung. Die logische Ursache liegt in der zu früh festgelegten DB-Locale und im fehlenden konsistenten Client-/Server-Codepfad.
In der Praxis ist die saubere Korrektur meist:
Bei dbexport/dbimport die erzeugte Schema-Datei im Exportverzeichnis vor dem Import prüfen. Sie kann das ursprüngliche CREATE DATABASE-Statement und damit die bisherige Locale enthalten; nicht ungeprüft annehmen, dass dbimport automatisch die gewünschte Ziel-Locale verwendet. Falls nötig, den Datenbankkopf in der Schema-Datei auf die Zieldefinition anpassen. DB_LOCALE muss zur Ziel-Datenbank passen; CLIENT_LOCALE muss beim Export und Import jeweils zur tatsächlichen Kodierung der Textdateien passen. Nach dem Import Daten, Collation-Verhalten und neu angelegte Indizes verifizieren.
Ein valider Admin-Workflow für die Diagnose sieht typischerweise so aus:
Ein typischer Entscheidungsbaum:
→ wahrscheinliches Codeset-/Konvertierungsproblem
→ wahrscheinliches Collation-Problem
→ Collation oder Locale-Semantik ist die Ursache
→ codeset-/CLIENT_LOCALE-/DB_LOCALE-Mismatch
Im Betrieb sollte die Korrektur immer dem Ursachepfad folgen:
Wenn zwei dieser Ebenen nicht zusammenpassen, entstehen die typischen Probleme mit ä, ö, ü, ß und anderen Sonderzeichen.
Symptom A: Zeichen werden als ü, ä, ö dargestellt
Ursache:
Prüfung:
locale env | grep -E 'LANG|LC_|CLIENT_LOCALE|DB_LOCALE'
SELECT name, LENGTH(name) FROM TABLE_NAME WHERE name LIKE '%M%';
Korrektur:
export CLIENT_LOCALE=en_US.819 export DB_LOCALE=en_US.819
Falls die Datenbank bereits im falschen Codeset steht, keine reine Laufzeitkorrektur, sondern neue DB oder sauberer Transfer planen.
Symptom B: ORDER BY oder Unique zeigt falsche Reihenfolge
Ursache:
Prüfung:
SELECT col FROM tab ORDER BY col; SELECT col, COUNT(*) FROM tab GROUP BY col HAVING COUNT(*) > 1;
Korrektur:
Symptom C: Import/Export zeigt Umlaute erst nach Transfer falsch
Ursache:
Prüfung:
file datafile hexdump -C datafile | head
Korrektur:
Umlaute oder Sonderzeichen werden im Informix-System falsch dargestellt, sortieren falsch oder erzeugen Unique-/Vergleichsfehler.
Die häufigste Ursache ist keine fehlende Informix-Funktionalität, sondern ein Mismatch zwischen:
locale env | grep -E 'LANG|LC_|CLIENT_LOCALE|DB_LOCALE'
SELECT name, VALUE FROM sysmaster:sysdbslocale WHERE name IN ('dbs_collate', 'dbs_cset');
SELECT col, LENGTH(col), col = 'Müller' AS eq_mueller, col = 'Muller' AS eq_muller FROM tab LIMIT 10;
SELECT col FROM tab ORDER BY col;
file exportfile hexdump -C exportfile | head
export CLIENT_LOCALE=en_US.819 export DB_LOCALE=en_US.819
Oder mit UTF-8:
export CLIENT_LOCALE=en_US.utf8 export DB_LOCALE=en_US.utf8
Wenn die Datenbank bereits mit einem falschen Codeset oder falscher Collation angelegt wurde:
CREATE DATABASE db_new WITH LOG DB_LOCALE = 'en_US.819@dict' CLIENT_LOCALE = 'en_US.819';
Danach Daten mit konsistenter Locale transferieren und die Ergebnisse erneut prüfen.
SELECT col, LENGTH(col), col = 'Müller' AS eq_mueller, col = 'Muller' AS eq_muller FROM tab ORDER BY col;
locale
Erwartung:
Für den Admin ist die wichtigste Frage nicht „Ist @dict aktiv?“, sondern:
Checkliste:
Wenn ein ü in der Datenbank anstelle von UTF-8-C3-BC als FC auftaucht, ist der Speicher korrekt für 819. Wenn der Client aber UTF-8-Strings liefert und der Server 819 erwartet, entsteht ein Konvertierungsfehler. Das muss am Übergang korrigiert werden, nicht durch einen Collation-Wechsel.
locale env | grep -E 'LANG|LC_|CLIENT_LOCALE|DB_LOCALE'
SELECT name, VALUE FROM sysmaster:sysdbslocale WHERE name IN ('dbs_collate', 'dbs_cset');
export CLIENT_LOCALE=en_US.819 export DB_LOCALE=en_US.819
Oder:
export CLIENT_LOCALE=en_US.utf8 export DB_LOCALE=en_US.utf8
Wenn die DB bereits falsch angelegt wurde:
CREATE DATABASE db_new WITH LOG DB_LOCALE = 'en_US.819@dict' CLIENT_LOCALE = 'en_US.819';
SELECT col, LENGTH(col), col = 'Müller' AS eq_mueller, col = 'Muller' AS eq_muller FROM tab ORDER BY col;
Erwartung:
Die folgenden IBM-Dokumentationsstellen sind die maßgeblichen offiziellen Referenzen für die Kernregeln von Informix GLS und Locales:
Hinweis: IBM-Dokumentation kann je nach Version und Produktseite leicht verlinkt werden; die oben genannten Referenzen sind die offiziellen Einstiegspunkte für die hier beschriebenen Funktionen.
Das entscheidende technische Ergebnis lautet:
Nur wenn Codeset, Collation und Client-Locale zusammenpassen, funktionieren ä, ö, ü, ß korrekt in Informix.
Beispiel für eine Linux-/bash-Umgebung, in der der Client als UTF-8 arbeitet und die DB als 819 erwartet:
export LANG=en_US.UTF-8 export LC_ALL=en_US.UTF-8 export CLIENT_LOCALE=en_US.utf8 export DB_LOCALE=en_US.819
Beispiel für eine Latin-1-/819-Spezifikation im Client:
export LANG=en_US.ISO8859-1 export LC_ALL=en_US.ISO8859-1 export CLIENT_LOCALE=en_US.819 export DB_LOCALE=en_US.819
Wichtig: Diese Werte sind nur richtig, wenn die Anwendung wirklich exakt in diesem Codeset arbeitet. Ein falscher oder „nur vermuteter“ Wert erzeugt echte Byte-Verzerrungen.
CREATE DATABASE dbname WITH LOG IN dbspace1 DB_LOCALE = 'en_US.819@dict' CLIENT_LOCALE = 'en_US.819' MODE ANSI;
Oder ebenfalls üblich:
CREATE DATABASE dbname WITH LOG DB_LOCALE = 'en_US.819' CLIENT_LOCALE = 'en_US.utf8';
Das ist der kritische Punkt: Nach dem CREATE DATABASE ist diese Locale für die DB fest. Ein späteres Setzen von CLIENT_LOCALE oder DB_LOCALE in der Shell ändert die bereits vorhandenen Daten nicht.
SELECT name, VALUE FROM sysmaster:sysdbslocale WHERE name IN ('dbs_collate', 'dbs_cset');
Wenn die DB definiert ist, zeigt die Datenbankkataloginformation, welcher Codeset und welche Collation für die DB gelten. Das ist der richtige Nachweis, nicht die aktuelle Shell-Umgebung.
echo "$LANG" echo "$LC_ALL" echo "$CLIENT_LOCALE" echo "$DB_LOCALE" locale
Prüfungen, die in der Praxis sinnvoll sind:
locale charmap iconv --list | grep -Ei 'UTF-8|ISO-8859-1|IBM-819'
Wenn der Client als UTF-8 deklariert ist, aber tatsächlich Latin-1-Bytes ausliefert, ist die Konvertierung falsch, obwohl die Shell-Umgebung „gut“ aussieht.
Beispiel A: Datenbank ist 819, Client ist korrekt als 819 gesetzt.
CREATE TABLE test_umlaut ( id SERIAL, name VARCHAR(50) ); INSERT INTO test_umlaut(name) VALUES ('Müller'); SELECT name, LENGTH(name) FROM test_umlaut;
Erwartung:
Beispiel B: Client liefert UTF-8, DB erwartet 819.
SET CLIENT_LOCALE 'en_US.utf8'; INSERT INTO test_umlaut(name) VALUES ('Müller');
Wenn die Client-Umgebung nicht exakt mit den tatsächlich gesendeten Bytes übereinstimmt, kann der String als falsche Bytefolge interpretiert werden. Der Gefahrensignal: sichtbare Verzerrung, Spracheingang fehlerhaft, Abweichungen bei LENGTH oder ORDER BY.
CREATE TABLE test_sort ( id SERIAL, name VARCHAR(20) ); INSERT INTO test_sort(name) VALUES ('Muller'), ('Müller'), ('Muller2'); SELECT name FROM test_sort ORDER BY name;
Erwartung:
Beispiel für einen Import-Workflow mit festem Client-Codeset:
export CLIENT_LOCALE=en_US.819 export DB_LOCALE=en_US.819 # Beispiel: Export mit konsistentem Format # Danach Import in die Ziel-DB mit derselben DB_LOCALE
Wenn Import/Export mit widersprüchlichen Locales läuft, wird das Zeichenmaterial falsch geordnet oder verfälscht.
SELECT name, LENGTH(name), name = 'Müller' AS match_1, name = 'Muller' AS match_2 FROM test_umlaut; SELECT name FROM test_sort ORDER BY name;
Ziel dieser Prüfung:
1. Werden Zeichen verzerrt dargestellt? Ja -> Codeset-/Konvertierungsproblem prüfen Nein -> Sortier-/Collation-Problem prüfen 2. Sind Daten in DB bereits gespeichert? Ja -> DB_LOCALE und DB-Definition prüfen, kein bloßes SET erwartet Nein -> CREATE DATABASE / locale-Definition erneut prüfen 3. Ist CLIENT_LOCALE konsistent mit den tatsächlich gelieferten Bytes? Nein -> Client- oder Import-Fehler Ja -> DB_LOCALE prüfen 4. Ist ORDER BY / LIKE / Unique inkonsistent? Ja -> Collation und @dict prüfen Nein -> auf Export/Import oder Anwendungskodierung schauen
Minimaler, robuster Ablauf:
# 1. Umgebung prüfen locale env | grep -E 'LANG|LC_|CLIENT_LOCALE|DB_LOCALE' # 2. Ziel-DB mit korrekter Locale anlegen # CREATE DATABASE ... DB_LOCALE = 'en_US.819@dict' # 3. Client auf dieselbe Semantik stellen export CLIENT_LOCALE=en_US.819 # 4. Daten transferieren, danach Byte- und Vergleichsprüfungen durchführen
Wichtig: Wenn die vorhandene DB bereits im falschen Codeset bzw. mit falscher Collation erstellt wurde, ist eine reine Laufzeit-Umstellung meistens keine saubere Lösung. Dann ist eine neue, korrekt definierte DB oder eine glasklare Migration die belastbare Korrektur.
Informix, GLS, Locale, DB_LOCALE, CLIENT_LOCALE, Codeset, Collation, @dict, ISO-8859-1, CCSID-819, Latin-1, UTF-8, Unicode, deutsche Umlaute, äöüß, Byte-Repräsentation, Datenbankspeicher, ORDER BY, BETWEEN, LIKE, Unique-Index, String-Länge, Substring, Mojibake, dbload, UNLOAD, Import, Export, Replication, ER, Encoding, Character Conversion, Client-Server-Konvertierung, Datenbankadministrator, Troubleshooting, CREATE DATABASE, locale-check, hex-dump, shell-environment