Change Characterset of a Database

Hintergrund

Bei der Installation einer Oracle DB ist ein Character Set anzugeben. Angaben wie WE8ISO8859P1, AL32UTF8, AL16UTF16, WE8MSWIN1252, etc. sind allen, die zuweilen Oracle Datenbanken installieren schon einmal über den Weg gelaufen. Ohne jetzt über Vor- und Nachteile von "herkömmlichen" und UTFx Zeichensätzen zu diskutieren, geht es hier nur darum einen "falschen" Character Set zu ändern (ansonsten mal hier schauen (Lächeln) ).
Falsch kann sich z. B. so äußern. Bei einem import Vorgang:
Export-Datei wurde von EXPORT:V10.02.01 über konventionellen Pfad erstellt
Importvorgang mit Zeichensatz WE8MSWIN1252 und Zeichensatz AL16UTF16 NCHAR durchgeführt
Import-Server verwendet Zeichensatz AL32UTF8 (mögliche Zeichensatzkonvertierung)
Export-Client verwendet Zeichensatz WE8ISO8859P1  (mögliche Zeichensatzkonvertierung)
Das ist zunächst nicht dramatisch, die Zeichensatzkonvertierung von WE8ISO8859P1 in AL32UTF8 führt aber dazu, dass z.B. ein Umlaut jetzt statt einem Byte zwei Byte benötigt. Das macht Probleme, wenn man eine Spalte hat, die als CHAR(40 BYTE) definiert ist:
Es folgt dann folgende Fehlermeldung:
[...]
ORA-12899: Wert zu groß für Spalte "USER"."TABLE"."ATTRIBUT" (aktuell: 41, maximal: 40)
[...]
Spalte 15 Süd
[...]
Da die Spalte als Char definiert ist, wird immer mit Leerzeichen aufgefüllt. Mitsamt den 37 Leerzeichen kommt man so auf 41 Zeichen im UTF8-Zeichensatz.
Besser wäre es nun, man hätte das Feld als CHAR(40 CHAR) definiert. Oder da CHAR gegenüber VARCHAR2 ohnehin nur Nachteile bringt noch besser als VARCHAR2(40 CHAR).
Normalerweise gibt man bei der Spaltendefinition ohnehin nur die Länge an, d.h. man schreibt einfach VARCHAR(40). Ob man dann VARCHAR2(40 CHAR) oder VARCHAR2(40 BYTE) bekommt, bestimmt der Datenbankparameter NLS_LENGTH_SEMANTICS (BYTE/CHAR):
select * from nls_database_parameters;
select * from nls_instance_parameters;
select * from nls_session_parameters;
Diesen kann man mit alter database anpassen. Das nützt einem aber leider nichts, wenn man die Daten mit dem konventionellen Import importiert. In der Importdatei ist offensichtlich hinterlegt, dass das Feld den Datentyp CHAR(40 BYTE) (z.B.) hat. Es gibt auch keinen Import-Parameter, mit dem man das beeinflussen kann. (Zum Import mit der Datapump liegen mir keine Erfahrungen vor.)
Es hilft also nichts, wir müssen den Zeichensatz ändern. Das Ändern des Zeichensatzes war ganz früher (vor oracle 8?) nicht möglich und ist vielen vielleicht auch heute noch nicht bekannt.

Ausweg

Vorher, falls es keine neu installierte DB ist, ein Backup...
connect / as sysdba
shutdown immediate;
startup mount;
alter system enable restricted session;
alter system set job_queue_processes=0;
alter database open;
alter database character set internal_use WE8ISO8859P15; --(nicht WE8ISO8859P1 nehmen, dann fehlt nämlich das Euro-Zeichen)
shutdown immediate;
startup;
select * from nls_database_parameters;

Dieser Artikel hat neben mir noch weitere Autoren.

No comments:

Post a Comment