juanjonavarro.com

secciones

Convertir un Oracle 11g XE a un juego de caracteres single byte

Esto me ha costado un poco, así que lo documento por aquí, por si alguien necesita hacerlo.

Lo primero, ¿por qué querríamos convertir un Oracle a un juego de caracteres single byte (por ejemplo WE8MSWIN1252)?

Vaya por delante que esto no es algo que esté recomendado hacer para una máquina en producción. Por defecto, el juego de caracteres de Oracle 11g Express Edition es multi byte (UTF8, creo). En este juego de caracteres, cada carácter utiliza entre 1 y 3 bytes y a priori esto no tiene nada de malo. Mi problema es que en ocasiones tengo que trabajar con bases de datos de clientes que tienen un Oracle single byte y al hacer la importación a mi sistema algunos datos superan la capacidad de la columna (en la bbdd del cliente 40 caracteres ocupan 40 bytes mientras que en la mía 40 caracteres pueden ocupar 40+x bytes, superando el tamaño de la columna de la tabla). La versión anterior (10g) se podía descargar en versión single byte, pero en la versión 11g esto ya no es posible.

La solución es convertir Oracle a un juego de caracteres single byte nada más instalarlo. Hay varias formas de hacer esto. A continuación indico cómo hacerlo a las bravas (recuerda, esto es una bbdd de desarrollo)

Antes de nada, si necesitas saber cual es juego de caracteres por defecto de tu base de datos:

select value from NLS_DATABASE_PARAMETERS where parameter=’NLS_CHARACTERSET’;

Nos conectamos como sysdba y ejecutamos las siguientes sentencias:

sqlplus sys as sydba
SQL> shutdown immediate;
SQL> startup restrict
SQL> ALTER DATABASE CHARACTER SET INTERNAL_USE WE8MSWIN1252 ;
SQL> shutdown immediate;
SQL> startup

Después de esto ya tendremos la bbdd en el juego de caracteres single byte WE8MSWIN1252.

Me encontré con un problema después de esto, y es que al intentar importar con impdp me daba el siguiente error:

"ORA-39213: Metadata processing is not available"

Para solucionarlo hay que hacer lo siguiente:

SQL> execute dbms_metadata_util.load_stylesheets

Pero (error dentro del error) al intentar hacerlo me daba el siguiente error:

BEGIN dbms_metadata_util.load_stylesheets; END;

*
ERROR at line 1:
ORA-31609: error loading file "kucolumn.xsl" from file system directory
"C:\oraclexe\app\oracle\product\11.2.0\server\rdbms\xml\xsl"
ORA-06512: at "SYS.DBMS_METADATA_UTIL", line 2397
ORA-06512: at line 1

Se queja de que no existe un fichero en el directorio $SERVER/rdbms/xml/xsl y es que el problema es que la versión XE de Oracle 11g realmente no incluye ese directorio. La solución es copiar ese directorio de otra instalación de Oracle (no XE) de donde lo podamos coger. ¿Y si no tenemos una instalación así a mano? Ese era mi problema, y encontré la solución en este foro. Se trata de descargar el fichero win32_11gR2_database_1of2.zip del sitio de Oracle (ahora mismo está aquí) y coger el fichero \database\stage\Components\oracle.rdbms\11.2.0.1.0\1\DataFile\filegroup21.jar de su interior. A su vez abres ese fichero (lo puedes hacer con 7-Zip) y en su interior puedes encontrar ese directorio xsl.

¿Eso es todo? No, porque, rizando el rizo, aún nos faltará un fichero dentro de ese directorio xsl. El fichero que falta es kupostdt.xsl, el cual tienes que crear a mano con el siguiente contenido:

<?xml version="1.0"?>
<!--
NAME
    kupostdt.xsl
DESCRIPTION
    XSLT stylesheet for XML => DDL conversion of ku$_post_data_table_t ADTs
NOTES
    Do NOT modify this file under any circumstance. Copy the file
    if you wish to use this stylesheet with an external XML/XSL parser

MODIFIED        MM/DD/YY
    sdavidso 06/08/09 - new stylesheet - for minimize records_per_bock
 -->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <!-- Import required scripts -->
 <xsl:import href="kucommon.xsl"/>
 <!-- Top-level parameters -->
 <xsl:param name="PRETTY">1</xsl:param>
 <xsl:param name="SQLTERMINATOR">1</xsl:param>
 <!-- params for parse -->
 <xsl:param name="PRS_DDL">0</xsl:param>
 <xsl:param name="PRS_DELIM">\{]`</xsl:param>
 <xsl:param name="PRS_VERB">0</xsl:param>
 <xsl:param name="PRS_OBJECT_TYPE">0</xsl:param>
 <xsl:param name="PRS_SCHEMA">0</xsl:param>
 <xsl:param name="PRS_NAME">0</xsl:param>
 <xsl:param name="PRS_GRANTEE">0</xsl:param>
 <xsl:param name="PRS_GRANTOR">0</xsl:param>
 <xsl:param name="PRS_BASE_OBJECT_TYPE">0</xsl:param>
 <xsl:param name="PRS_BASE_OBJECT_SCHEMA">0</xsl:param>
 <xsl:param name="PRS_BASE_OBJECT_NAME">0</xsl:param>
 <xsl:template match="POST_DATA_TABLE_T">
  <!-- *******************************************************************
Template: POST_DATA_TABLE_T - template for table attributes
which can only be set after table data is loaded.
******************************************************************** -->
  <xsl:call-template name="DoParse">
   <xsl:with-param name="Verb">ALTER</xsl:with-param>
   <xsl:with-param name="ObjectType">POST_DATA_TABLE</xsl:with-param>
   <xsl:with-param name="SchemaNode" select="SCHEMA_OBJ/OWNER_NAME"/>
   <xsl:with-param name="NameNode" select="SCHEMA_OBJ/NAME"/>
  </xsl:call-template>
  <xsl:if test="(SPARE1 mod 65536)>=32768">
   <xsl:text> ALTER TABLE </xsl:text>
   <xsl:apply-templates select="SCHEMA_OBJ"/>
   <xsl:text>MINIMIZE RECORDS_PER_BLOCK</xsl:text>
  </xsl:if>
 </xsl:template>
</xsl:stylesheet>

Y fin. Con esto ya podremos ejecutar nuestro:

SQL> execute dbms_metadata_util.load_stylesheets

… y después ya nos funcionará el import.

Exhausto

Artículos anteriores...

El "Gran Cañon" chino

Leyendo esta recomendación sobre el uso de la construcción “//” al principio de una url para que se autoajuste a http o https (resumen: no lo hagas, usa siempre https) he leído sobre lo que llaman el Great Cannon chino. Según... seguir leyendo

Stacktraces "perdidas" en Java

Hoy, revisando un log de error de una aplicación Java me he encontrado con una cosa curiosa y que nunca había visto: Se estaba registrando una excepción, pero en lugar de mostrar toda la traza de la pila de llamadas... seguir leyendo

Codificación de URLs

En What every web developer must know about URL encoding se explica algo que resulta sorprendentemente difícil de hacer bien: Hacer encoding de URLs. Algunas cosas destacables: Las distintas partes de una url (el host, el path, el querystring) utilizan distintas codificaciones,... seguir leyendo

...leer el archivo completo