Como ya habíamos visto en artículos anteriores, el CHARACTER SET nos determina cuales caracteres se pueden guardar en una columna cuyo tipo de datos es CHAR o VARCHAR. Esto es importante para nosotros pues normalmente en una columna de alguno de esos tipos de datos necesitaremos guardar letras acentuadas, letras eñe y letras u con diéresis. O sea, letras de uso frecuente en el idioma castellano.

¿Qué es transliteración?

Se llama transliteración a convertir los caracteres que están en un CHARACTER SET a otro CHARACTER SET.

Cuando Firebird hace transliteración preserva la fidelidad de los caracteres. Es decir que nunca sustituye un carácter que está en el CHARACTER SET original pero que no está en el CHARACTER SET destino. El propósito de esta restricción es garantizar que se pueda convertir un texto de un CHARACTER SET al otro, en ambas direcciones, y sin perder ni un solo carácter en el proceso.

¿Cómo podemos realizar la transliteración?

Si tenemos una una columna cuyo CHARACTER SET es equivocado, ¿cómo lo cambiamos?

Por ejemplo, nuestra columna usa NONE y queremos cambiarlo por ISO8859_1

Bien, hay dos métodos que podemos usar:

  1. ALTER TABLE
  2. Columna adicional

Método 1. Usando ALTER TABLE

Si usamos ALTER TABLE escribiríamos algo como:

ALTER TABLE 
   MiTabla 
ALTER COLUMN 
   MiColumna 
TYPE 
   VARCHAR(MiNúmero) 
CHARACTER SET 
   ISO8859_1;

COMMIT;

Método 2. Usando una columna adicional

Si usamos una columna adicional entonces tendríamos que hacer lo siguiente:

  • Crear una columna temporaria con el CHARACTER SET correcto
  • Copiar en la columna temporaria el contenido de la columna original, usando OCTETS como un CHARACTER SET intermedio
  • Borrar la columna original
  • Crear una nueva columna con el mismo nombre de la columna original y el CHARACTER SET correcto
  • Copiar en la nueva columna el contenido de la columna temporaria
  • Borrar la columna temporaria

¿Por qué usamos OCTETS en la columna temporaria?

Porque OCTETS es un CHARACTER SET especial, que guarda lo mismo que se escribió, o sea, no realiza la transliteración.

Entonces, escribiríamos algo como:

ALTER TABLE
   MiTabla
ADD
   MiColumnaISO8859_1 VARCHAR(40) CHARACTER SET ISO8859_1;

COMMIT;

UPDATE
   MiTabla
SET
   MiColumnaISO8859_1 = CAST(MiColumnaOriginal AS VARCHAR(40) CHARACTER SET OCTETS);

COMMIT;

ALTER TABLE
   MiTabla
DROP
   MiColumnaOriginal;

COMMIT;

ALTER TABLE
   MiTabla
ADD
   MiColumnaOriginal VARCHAR(40) CHARACTER SET ISO8859_1;

COMMIT;

UPDATE
   MiTabla
SET
   MiColumnaOriginal = MiColumnaISO8859_1;

COMMIT;

ALTER TABLE
   MiTabla
DROP
   MiColumnaISO8859_1;

COMMIT;

Desde luego que VARCHAR(40) es solamente un ejemplo, tú usarás CHAR() o VARCHAR() con la cantidad de caracteres que sea la adecuada en tu caso.

¿Cuál de los dos métodos es preferible usar?

Habrás notado que el Método 1 es mucho más sencillo de realizar que el Método 2, entonces ¿por qué no usar siempre el Método 1?

Lo que ocurre es que si usas el Método 1 el Firebird no cambia el texto que se encuentra en MiColumna, ese texto continúa allí exactamente como estaba. Solamente se cambian los metadatos de la tabla, pero no los datos de esa tabla, éstos permanecen exactamente igual que antes de cambiar el CHARACTER SET.

El Firebird realmente cambiará los datos cuando hagas un UPDATE o un SELECT que involucren a esa columna. Mientras no hagas ni un UPDATE ni un SELECT los datos continuarán con el CHARACTER SET antiguo. ¿Por qué actúa así? Porque el Firebird no quiere perder el tiempo en actualizar todas las filas de la tabla, una tabla que quizás tiene millones y millones de filas.

Cuando ejecutas un comando UPDATE o un comando SELECT que involucren a esa columna, esto puede (potencialmente) producir un error ya que algunos bytes en ISO8859_1 pueden no ser válidos.

En cambio, si usas el Método 2 la validación es realizada en el momento en que copias los datos de una columna a la otra y si ocurre algún error podrás subsanarlo en ese momento.

En síntesis, la principal diferencia es que si hay algún error y usaste el Método 1 muy probablemente será el usuario de tu aplicación quien lo descubrirá y seguramente se quejará. Pero si usas el Método 2 serás tú quien lo descubra.

Conclusión:

Lo más conveniente para quienes creamos bases de datos cuyos textos se introducirán en idioma castellano (español) es que el CHARACTER SET sea ISO8859_1. Si alguna columna de alguna tabla no tiene ese CHARACTER SET y deseamos que lo tenga, hay dos métodos que podemos usar. Uno de ellos es ALTER TABLE y el otro es creando una columna temporaria.

El primer método es más rápido, pero no valida que todos los caracteres del CHARACTER SET original tengan correspondencia con los caracteres del nuevo CHARACTER SET. Aunque se puede escribir un SELECT para verificarlo.

El segundo método es más lento, pero sí realiza esa validación. Además, como al escribir el comando UPDATE o el comando SELECT no tendrá que estar cambiando el CHARACTER SET también esos comandos se ejecutarán más rápido.

Artículos relacionados:

Entendiendo a los conjuntos de caracteres

Algo más sobre los conjuntos de caracteres

Funciones útiles con los conjuntos de caracteres

Máxima cantidad de columnas en una tabla

El índice del blog Firebird21

El foro del blog Firebird21