Contexte
Lors d'un changement de charset depuis un charset monobyte (comme le MSWIN1252 ou le WE8ISO9959P1) vers un charset multi-bytes (comme le AL32UTF8 ou l'UTF8) un phénomène d'agrandissement des tailles en octets des chaines de caractères converties vont probablement entrainer des rejets si une opération classique d'export/import est jouée. Par exemple lorsqu'une table est créée, la taille d'un champs caractère est fixée définitivement. Un VARCHAR(50) dans un CS mono-byte aura une taille de 50 octets (bytes). Si pour une ligne donnée, les 50 octets sont occupées totallement par une chaine de caractères dont au moins un des caractères n'est pas dans les caractères ANSI de base (€, §,@,...) ces caractères auront une taille de 2 octets (voir plus) dans un CS comme l'UTF8.
l'export (datapump naturellement !) depuis une base source (en MS1252 par exemple) va générer un fichier dump, ce fichier s'il est pris tel-quel et qu'un import est joué sur une base cible en UTF8, il sera interprété par l'import en créant les tables avec des colonnes dont la taille en octet sera telle que défini dans la base source (VARCHAR2(50) BYTES par exemple) et ceci même si on positionne un NLS_LENGTH_SEMANTICS à CHAR en cible. L'import créra donc des tables ayant des colonnes dont la tailles max sera insuffisantes pour stocker tous les caractères des chaines sources converties dans le CS cible. Les lignes seront rejetées.
Vous pouvez avoir une idée des "dégats" en lancer l'utilitaire CSSCAN disponible dans le répertoire $ORACLE_HOME/rdbms/admin/scripts
Voici donc comment faire pour s'en sortir en intervenant sur le script de création des tables pour forcer ces creates à incorporer des VARCHAR2(x) CHAR en définition de colonne.
L’objectif de cet article est de décrire précisément la procédure à exécuter pour effectuer la bascule du jeu de caractère MSWIN1252 (ou WE88859Px) en UTF8 sur une nouvelle base de données
Pré-requis :
La base de données de destination est disponible et le jeu de caractères est déjà en UTF8.
Les schémas sont supprimés sur la base de données de destination.
Toutes les manipulations sont effectuées à partir d’un export DATAPUMP « FULL » de la base de données source.
1 – Etape 1 – Export des Users et tables
L’objectif de cet export est de générer le DDL de création des USERS et TABLES avant d’effectuer la modification sur la description des colonnes de type VARCHAR (passage du type BYTE au type CHAR).
Le script suivant effectue la génération du DDL correspondant à la création des users et des tables pour effectuer les modifications :
$ impdp login/mdp DUMPFILE=FICHIER_DUMP_%U.dmp LOGFILE=FICHIER_LOG.log DIRECTORY=DMPDMP PARALLEL=8 CONTENT=METADATA_ONLY SQLFILE=FICHIER_SQL.sql SCHEMAS=LISTE_SCHEMAS INCLUDE=TABLE/TABLE INCLUDE=DATABASE_EXPORT/SCHEMA/ROLE_GRANT INCLUDE=DATABASE_EXPORT/SCHEMA/TABLE/GRANT INCLUDE=ROLE_GRANT INCLUDE=USER INCLUDE=DATABASE_EXPORT/SCHEMA/TABLESPACE_QUOTA INCLUDE=DATABASE_EXPORT/ROLE
La commande “SQLFILE=” génère le DDL dans un fichier SQL qui sera repris dans l’étape suivante.
Les INCLUDE permettent d’importer uniquement ce qui nous intéresse à ce moment de la procédure (les tables, les utilisateurs et les droits, quotas et rôles).
2 – Etape 2 – Remplacement BYTE par CHAR dans le DDL de création des tables
L’étape suivante consiste à remplacer les « BYTE) » par « CHAR) » dans le fichier SQL généré. La commande appelée est « sed ».
sed 's/ BYTE)/ CHAR)/g' FICHIER_SQL.sql>FICHIER_SQL_modif.sql
Les chaînes de caractères « BYTE) » sont remplacées par « CHAR) » dans un fichier modifié. L’import de la structure des tables de la base de données peut donc être effectué dans l’étape suivante.
3 – Etape 3 – Import de la structure de la base de données
Dans cette étape, l’intégration du fichier se fait par l’intermédiaire de la commande SQLPLUS.
$ sqlplus login/mdp @FICHIER_SQL_modif.sql
La structure des tables de la base de données est importée, l’import des data se fait à l’étape suivante.
4 – Etape 4 – Import des données
L’import des données («CONTENT=DATA_ONLY ») avec l’option « TABLE_EXISTS_ACTION=TRUNCATE » est effectué à l’aide du script suivant :
$ impdp login/mdp DUMPFILE= FICHIER_DUMP_%U.dmp LOGFILE= FICHIER_LOG.log DIRECTORY=DMPDMP PARALLEL=8 CONTENT=DATA_ONLY TABLE_EXISTS_ACTION=TRUNCATE SCHEMAS= LISTE_SCHEMAS
Les tables sont importées et chargées, il ne reste plus qu’à importer les autres objets.
5 – Etape 5 – Import des objets manquants
Cette étape consiste donc à effectuer un dernier import des métadonnées (« CONTENT=METADATA_ONLY ») du dump avec exclusion des objets importés en étape 1.
$ impdp login/mdp DUMPFILE= FICHIER_DUMP_%U.dmp LOGFILE= FICHIER_LOG.log DIRECTORY=DMPDMP PARALLEL=8 CONTENT=METADATA_ONLY SCHEMAS= LISTE_SCHEMAS EXCLUDE=TABLE/TABLE EXCLUDE=DATABASE_EXPORT/SCHEMA/ROLE_GRANT EXCLUDE=DATABASE_EXPORT/SCHEMA/TABLE/GRANT EXCLUDE=ROLE_GRANTEXCLUDE=USER EXCLUDE=DATABASE_EXPORT/SCHEMA/TABLESPACE_QUOTA EXCLUDE=DATABASE_EXPORT/ROLE