3 votes

Comment faire pour que les diablotins utilisent le bon jeu de caractères ?

J'essaie d'importer un fichier dmp d'une base de données vers une autre. Le problème est que certains caractères spéciaux danois ne sont pas importés correctement car une conversion de la carte de caractères est effectuée pendant l'importation.

C'est l'information que je reçois lorsque je lance l'importation avec imp (voir la note sur la conversion possible des caractères) :

Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

Export file created by EXPORT:V10.02.01 via conventional path

import done in WE8ISO8859P1 character set and AL16UTF16 NCHAR character set
import server uses AL32UTF8 character set (possible charset conversion)
. importing USERNAME's objects into USERNAME    
. . importing table                      "TABLE2" 
IMP-00019: row rejected due to ORACLE error 12899
IMP-00003: ORACLE error 12899 encountered
ORA-12899: værdi er for stor for kolonnen "USERNAME"."TABLE2"."NAME" (faktisk: 32, maksimum: 30)
Column 1 408261
Column 2 KUBEN FÆLLES MÅLER            

Chaque caractère spécial (généralement Æ, Ø et Å) utilise 2 caractères au lieu d'un, et les données sont remplies d'espaces, ce qui provoque une erreur car les données contiennent 31 caractères pour ce champ, et le champ est défini comme étant de taille 30.

L'exportation qui a généré le fichier dmp a été exécutée comme suit :

SET CHARACTERSET=WE8PC850
SET NLS_LANG=DANISH
SET NLS_NUMERIC_CHARACTERS=.,
exp username/password@server1 dumpfile.dmp

L'importation a été exécutée comme suit : Comment faire pour que cela fonctionne correctement ?

SET CHARACTERSET=WE8PC850
SET NLS_LANG=DANISH
SET NLS_NUMERIC_CHARACTERS=.,
imp username/password@server2 fromuser=username touser=username commit=y ignore=y file=dumpfile.dmp log=dumpfile.log

Que peut-on faire pour y remédier ? Il semble que le imp ignore le jeu de caractères utilisé, car le serveur d'importation utilise AL32UTF8 (ce qui est faux).

3voto

Vous importez des données dans une base de données en utilisant le jeu de caractères AL32UTF8 (c'est le jeu par défaut). L'importateur doit donc convertir les caractères pour qu'ils correspondent à ce jeu et certains deviendront des caractères multi-octets comme vous l'avez constaté. Il y a deux façons de traiter ce problème :

1) Si vous n'avez pas besoin d'Unicode dans la nouvelle base de données, recréez-la dans le même jeu de caractères que l'ancienne base de données. Exécutez ce code sur l'ancienne base de données pour obtenir le jeu de caractères et utilisez-le.

SELECT parameter, value
FROM nls_database_parameters
WHERE parameter
LIKE '%CHARACTERSET';

Une fois que la nouvelle et l'ancienne base de données ont le même jeu de caractères, l'importation ne devra pas faire la conversion.

2) Si vous pouvez pré-créer les tables, vous pouvez utiliser la fonction NLS_LENGTH_SEMANTICS paramètre. Si vous lui attribuez la valeur CHAR au lieu de la valeur par défaut BYTE, un VARCHAR2(5) se verra allouer suffisamment d'espace pour stocker 5 caractères dans le jeu de caractères de la base de données (potentiellement jusqu'à 20 octets) plutôt que 5 octets (ce qui pourrait n'autoriser qu'un seul caractère). Vous pouvez également modifier la DDL de création de table pour ajouter CHAR à chaque déclaration de colonne VARCHAR2, par exemple

CREATE TABLE xyz (column_x VARCHAR2(10 CHAR) NOT NULL);

De cette façon, vous pouvez convertir les données en Unicode et disposer d'un meilleur jeu de caractères pour l'avenir. Tant que votre application peut le supporter, cette méthode est peut-être la meilleure.

1voto

awe Points 227

Nous avons fini par résoudre ce problème en changeant tous les champs de caractères pour utiliser CHAR au lieu de l'option par défaut BYTE . Il s'agit essentiellement de l'option 2 proposée par @BrokenCrust sur sa réponse . Au lieu de recréer les tables, nous les avons simplement redéfinies en utilisant ce SQL :

set head off;
set linesize 1000;
set colsep ";";
set trimspool on;
set pagesize 0;
set verify off;
set feedback off;
set term off;
column dcol new_value mydate noprint;
select to_char(sysdate,'YYYY-MM-DD_HH24MISS') dcol from dual;
select to_char(sysdate,'YYYY-MM-DD') dcol from dual;
spool c:\temp\From_Byte_to_Char_og_VarChar2&mydate;
select '-- '||sysdate from dual;
select 'ALTER TABLE '||TABLE_NAME||
      ' MODIFY '||COLUMN_NAME||' CHAR('||data_length||' CHAR);' 
from 
     user_tab_cols
where 
     DATA_TYPE='CHAR'
;
select 'ALTER TABLE '||TABLE_NAME||
      ' MODIFY '||COLUMN_NAME||' VARCHAR2('||data_length||' CHAR);' 
from 
     user_tab_cols
where 
     DATA_TYPE='VARCHAR2'
;
select 'commit ;' from dual;
select 'exit ;' from dual;
spool off ;

0voto

Si vous utilisez oracle server XE, il n'est pas possible de modifier le jeu de caractères du serveur de base de données ou de toute base de données. Je suis également à la recherche d'une réponse.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X