Erfahrungsbericht: Unicode in der Datenbank Dierk Lenz 13. Juli 2011 DOAG Regio NRW Herrmann & Lenz Services GmbH • Gegründet 1995 • Firmensitz: Burscheid (bei Leverkusen) • Beratung, Anwendungsentwicklung, Schulung und Betrieb/Fernwartung rund um das Thema Oracle Datenbanken • Schwerpunktthemen: Hochverfügbarkeit, Tuning, Migrationen und Troubleshooting • Produkt: Monitoring Module • Viele DOAG-Aktivitäten Erfahrungsbericht: Unicode in der Datenbank 2 Was ist Unicode? Erfahrungsbericht: Unicode in der Datenbank 3 Wenn nicht mehr alle Sonderzeichen in die DB passen… • …dann nimmt man Unicode! – Standardisierter Zeichensatz (s.a. http://www.unicode.org) • Verschiedende Kodierungen – Fest oder variabel lang – Minimallänge 8, 16 oder 32 Bit • Oft verwendet: UTF-8 (variabel, Minimum 8 Bit, Maximum 32 Bit) Erfahrungsbericht: Unicode in der Datenbank 4 Unicode ist KEINE Oracle-Spezialität • Wird z.B. verwendet – in der Linux-Shell – unter Windows (manchmal, z.B. in .Net) • Verschiedene Kodierungen (UTF-8, UTF-16, UTF-32) und Versionen: – UTF8 entspricht ab Oracle 8.1.7 UTF-8 Version 3.0 – AL32UTF8 entspricht mit Oracle 10.2 UTF-8 Version 4.0, mit Oracle 11 Version 5.0 Erfahrungsbericht: Unicode in der Datenbank 5 Wozu verschiedene Kodierungen? • UTF-8 ist für Europa sehr gut geeignet: ASCIIZeichen bleiben bei 1 Byte, Umlaute usw. 2 Byte. • Indische Zeichen (Devanagari) belegen in UTF8 3 Byte, in UTF-16 2 Byte. Erfahrungsbericht: Unicode in der Datenbank 6 Wo stellt man das in Oracle ein? • Datenbank: CREATE DATABASE … CHARACTER SET AL32UTF8; • Client: NLS_LANG=American_Germany.AL32UTF8 Erfahrungsbericht: Unicode in der Datenbank 7 Einige Fakten • Unicode-DB und Non-Unicode-Client ist ebenso möglich wie Non-Unicode-DB und Unicode-Client! – Es werden immer nur die Zeichen richtig behandelt, die in beiden Zeichensätzen (DB und Client) vorkommen. • Beim Laden von Daten muss als ClientZeichensatz der Zeichensatz des Datenbestands angegeben werden. Erfahrungsbericht: Unicode in der Datenbank 8 Clients an Unicode-DBs • Wenn der Client z.B. einen WE8-Zeichensatz nutzt, arbeitet der Client mit Zeichen aus diesem Zeichensatz korrekt. • Somit könnte man z.B. für eine Adressverwaltung Arbeitsplätze für Westeuropa, Osteuropa usw. einrichten. • Vorsicht: Osteuropäischer Name und Wohnort Köln geht dann nicht… Erfahrungsbericht: Unicode in der Datenbank 9 Also: Wozu Unicode? • Mit Unicode kann jedes erdenkliche Zeichen in den Character-Feldern (VARCHAR2, CHAR, CLOB) einer Datenbank gespeichert werden! • Der Preis dafür ist, dass – zumindest einige – Zeichen länger als 1 Byte sind. Erfahrungsbericht: Unicode in der Datenbank 10 Eigentlich alles ganz einfach… Erfahrungsbericht: Unicode in der Datenbank 11 Kann man den Zeichensatz einer Datenbank auf Unicode ändern? • Ja, wenn Unicode eine strikte Obermenge des vorhandenen Zeichensatzes ist! • Wann ist Zeichensatz B eine strikte Obermenge von Zeichensatz A? Zwei Bedingungen: 1. Jedes in A kodierte Zeichen muss in B ebenfalls vorhanden sein (B Obermenge von A) 2. Jedes in A kodierte Zeichen muss in B den gleichen Codepoint haben. • Damit fallen praktisch alle Zeichensätze außer US7ASCII durch! • Eine Migration (Export/Import) ist notwendig! Erfahrungsbericht: Unicode in der Datenbank 12 Was heißt eigentlich VARCHAR2(n)? • CREATE TABLE uctab1 ( c VARCHAR2(6)) / • Antwort könnte sein: Bytes oder Zeichen! • Standard: Bytes (!) • Explizite Angabe möglich – VARCHAR2(6 BYTE) – VARCHAR2(6 CHAR) Erfahrungsbericht: Unicode in der Datenbank 13 Standardverhalten (NLSLängensemantik) • Ohne Angabe: NLS_LENGTH_SEMANTICS = BYTE | CHAR • Bestimmt lediglich Längensemantik beim Anlegen von Objekten. • Kein Einfluss auf Laufzeitverhalten Erfahrungsbericht: Unicode in der Datenbank 14 Was passiert bei Export/Import (von Non-Unicode nach Unicode)? • Die verwendete Längensemantik wird übernommen! • Z.B. Data Pump Import: ORA-02374: conversion error loading table "UC"."UCTAB1" ORA-12899: value too large for column C (actual: 7, maximum: 6) ORA-02372: data for row: C : 0X'4DDC4C4C4552' • Bei Byte-Semantik werden eventuell Datensätze nicht übernommen Erfahrungsbericht: Unicode in der Datenbank 15 Mögliche Auswege 1. Ändern der Längensemantik in der Quell-DB – Evtl. Auswirkungen auf laufende Anwendungen – Widerspricht dem Motto Never change a running system! 2. Importieren in modifizierte Tabellen – – – – – Z.B. Generieren von CREATE TABLE-Skripten Modifikation der Längensemantik Einspielen der Skripte Import in modifizierte Tabellen Erstellen der restlichen Strukturen (Indizes, Constraints, …) Erfahrungsbericht: Unicode in der Datenbank 16 Zweites Problem • CHAR-Längensemantik angegeben • Trotzdem wieder ORA-12899: value too large for column… • Grund: Harte Maximallänge (4000 Bytes für VARCHAR2, 2000 Bytes für CHAR) • Kreative Lösungen gefragt: – Kürzen von Feldinhalten – Umstieg auf CLOB Erfahrungsbericht: Unicode in der Datenbank 17 Hat meine Datenbank solche Probleme? • Antworten liefert u.a. das Database Character Set Scanner Utility CSSCAN. • Die besten Antworten liefert eine Testmigration. Erfahrungsbericht: Unicode in der Datenbank 18 CLOB und Unicode • CLOB- (und NCLOB-) Daten sind bei Multi-ByteZeichensätzen immer UCS-2-kompatibel kodiert (wenn DB-Zeichensatz UTF8 oder AL32UTF8) • UCS-2: 16 Bit-Kodierung, feste Länge, Vorgänger von UTF-16 • CLOBS verdoppeln ihre Größe bei der UnicodeMigration! • Apropos NCLOB: N-Datentypen werden nicht mehr benötigt! Erfahrungsbericht: Unicode in der Datenbank 19 Programmieren mit Unicode Erfahrungsbericht: Unicode in der Datenbank 20 Programmierte Objekte • Prozedur mit folgendem Code: CREATE OR REPLACE PROCEDURE ucproc1 AS vc VARCHAR2(6); BEGIN FOR r IN (SELECT c FROM uctab1) LOOP vc := r.c; END LOOP; END; / • Lässt man das auf einer Unicode-Umgebung laufen, passiert u.U. folgendes: ORA-06502: PL/SQL: numeric or value error: character string buffer too small ORA-06512: at "UC.UCPROC1", line 7 Erfahrungsbericht: Unicode in der Datenbank 21 PL/SQL Lösung • Fortgeschrittene PL/SQL-Programmierer kennen zur Deklaration vc VARCHAR2(6); die – sehr empfehlenswerte – Alternative vc uctab1.c%TYPE; Damit erbt der PL/SQL-Code die CHAR-Semantik der Tabelle – keine Anpassung notwendig! • Eine Überarbeitung des Codes ist oft notwendig. Erfahrungsbericht: Unicode in der Datenbank 22 Server-Einstellung NLS_LENGTH_SEMANTICS BYTE • Sollte bei Patches/Upgrades immer eingestellt sein. • Somit die gefahrlosere Einstellung. CHAR • Setzt den Standard für Sessions auf den Unicodekompatiblen Wert. • Besser für vergessliche Entwickler. Erfahrungsbericht: Unicode in der Datenbank 23 Entwicklungsumgebungen • Umgebungsvariable NLS_LENGTH_SEMANTICS auf CHAR • Session-Voreinstellung auf CHAR • Skripte immer mit ALTER SESSION SET nls_length_semantics = char; erzeugen! • Größter Aufwand bei besten Ergebnissen: Explizites Setzen der CHAR-Semantik bei jeder Deklaration! Erfahrungsbericht: Unicode in der Datenbank 24 Allgemeine Hinweise • Dokumentation: Globalization Support Guide • Neu auf Oracle Technology Network: Oracle Migration Assistant for Unicode http://www.oracle.com/technetwork/database/globalization/dmu/overview/index.html Erfahrungsbericht: Unicode in der Datenbank 25 Noch Fragen? • http://www.hl-services.de • [email protected] Erfahrungsbericht: Unicode in der Datenbank 26