Funciones útiles con los conjuntos de caracteres

4 comentarios

El Firebird dispone de 3 funciones que podemos usar cuando estamos tratando con conjuntos de caracteres, ellas son:

BIT_LENGTH() que nos devuelve la longitud de un string en bits

CHAR_LENGTH() que nos devuelve la longitud de un string en caracteres

OCTECT_LENGTH() que nos devuelve la longitud de un string en bytes

La diferencia entre ellas es notoria cuando se usan distintos conjuntos de caracteres, como en los ejemplos que vemos a continuación:

Ejemplo 1. Creando una Base de Datos que por defecto usa ISO8859_1

CHARSET1

Captura 1. Si haces clic en la imagen la verás más grande

Ahora le agregamos una tabla llamada TEST:

CREATE TABLE TEST (
   NOMBRE VARCHAR(40));

Y luego le insertamos algunas filas a esta tabla:

INSERT INTO TEST (NOMBRE) VALUES ('aeiou');
INSERT INTO TEST (NOMBRE) VALUES ('áéíóú');
INSERT INTO TEST (NOMBRE) VALUES ('HOLA');
INSERT INTO TEST (NOMBRE) VALUES ('HOLAaeiou');
INSERT INTO TEST (NOMBRE) VALUES ('HOLAáéíóú');

A continuación usamos las 3 funciones anteriores para ver los resultados que obtenemos:

SELECT
   NOMBRE,
   BIT_LENGTH(NOMBRE),
   CHAR_LENGTH(NOMBRE),
   OCTET_LENGTH(NOMBRE)
FROM
   TEST

CHARSET3

Captura 2. Si haces clic en la imagen la verás más grande

Lo que podemos notar es que usando el conjunto de caracteres ISO8859_1 siempre CHAR_LENGTH es igual a OCTET_LENGTH y que al multiplicar a cualquiera de ellos por 8 obtenemos BIT_LENGTH.

Ejemplo 2. Creando una Base de Datos que por defecto usa UTF8

 CHARSET2Captura 3. Si haces clic en la imagen la verás más grande

Ahora le agregamos una tabla llamada TEST:

CREATE TABLE TEST (
   NOMBRE VARCHAR(40));

Y luego le insertamos algunas filas a esta tabla:

INSERT INTO TEST (NOMBRE) VALUES ('aeiou');
INSERT INTO TEST (NOMBRE) VALUES ('áéíóú');
INSERT INTO TEST (NOMBRE) VALUES ('HOLA');
INSERT INTO TEST (NOMBRE) VALUES ('HOLAaeiou');
INSERT INTO TEST (NOMBRE) VALUES ('HOLAáéíóú');

A continuación usamos las 3 funciones anteriores para ver los resultados que obtenemos:

SELECT
   NOMBRE,
   BIT_LENGTH(NOMBRE),
   CHAR_LENGTH(NOMBRE),
   OCTET_LENGTH(NOMBRE)
FROM
   TEST

CHARSET4Captura 4. Si haces clic en la imagen la verás más grande

Y ahora lo que notamos es que CHAR_LENGTH es igual a OCTET_LENGTH solamente cuando se usan los caracteres ASCII, es decir cuando no hay vocales acentuadas. En cambio cuando hay vocales acentuadas cada una de ellas usa 2 octetos (ó 2 bytes, son sinónimos). En la última fila podemos ver que hay 9 caracteres pero que se necesitan 14 bytes para almacenarlos ¿por qué? porque cada letra no acentuada ocupa 1 byte y cada letra acentuada ocupa 2 bytes. Entonces, la palabra “HOLA” se guarda en 4 bytes y las vocales “áéíóú” se guardan en 10 bytes. La suma da 14 bytes.

En todos los casos BIT_LENGTH es igual a OCTET_LENGTH multiplicado por 8. Eso es lógico, ya que cada octeto (o byte, son sinónimos) tiene 8 bits.

Conclusión:

Como se puede ver en los ejemplos anteriores, si todo el texto que se introducirá en las columnas de tipo CHAR o VARCHAR estará en alguno de los idiomas europeos occidentales (español, portugués, francés, inglés, alemán, etc.) entonces debemos crear a nuestra Base de Datos con el conjunto de caracteres ISO8859_1 porque si usamos UTF8 cada vocal acentuada y cada letra eñe ocupará 2 bytes, en lugar de solamente 1 byte. Y por lo tanto, con ISO8859_1 se ahorra espacio y con UTF8 se desperdicia espacio.

¿Cuándo usaríamos UTF8? Cuando el texto puede estar escrito también con otros lenguajes europeos, como el checo, el polaco, el ruso, el ucraniano, etc. Si ese no es el caso, lo mejor es usar ISO8859_1 porque se ahorrará espacio en el disco duro.

Artículos relacionados:

Entendiendo a los conjuntos de caracteres

Algo más sobre los conjuntos de caracteres

Entendiendo COLLATE

Consultando sin importar mayúsculas ni acentos

El índice del blog Firebird21

El foro del blog Firebird21

Anuncios

Algo más sobre los conjuntos de caracteres

2 comentarios

Lo básico sobre los conjuntos de caracteres ya habíamos visto en este artículo:

Entendiendo a los conjuntos de caracteres

Y ahora haremos un repaso sobre ellos, que puede ser importante conocer:

  •  El conjunto de caracteres original, sobre el cual están basados todos los demás es el ASCII
  • El ASCII funciona perfectamente con el idioma inglés pero no sirve para los demás idiomas ya que no tiene vocales acentuadas ni vocales con diéresis ni eñes ni otros caracteres que se usan en otros idiomas
  • En un conjunto de caracteres se le asigna un número a cada carácter
  • En el ASCII esos números van desde el 0 hasta el 127. Dentro de esos 128 caracteres hay 32 que son invisibles y sirven para control (tecla ENTER, tecla TAB, tecla ESC, etc.)
  • Los números desde el 128 hasta el 255 están libres y pueden ser usados por otros conjuntos de caracteres
  • Un ejemplo son los llamados ISO8859 que están muy difundidos. Hay varias versiones, cada una de esas versiones usa los 128 caracteres sobrantes en su propia manera. Los caracteres desde el 128 hasta el 159 no están asignados y pueden ser usados para caracteres de control. Los caracteres adicionales que necesitan los distintos idiomas (español, portugués, francés, alemán, polaco, serbio, ruso, etc.) se codifican desde el 160 hasta el 255
  • El conjunto de caracteres ISO8859_1 tiene todos los caracteres de los idiomas europeos occidentales. Es el más ampliamente usado de los ISO8859 ya que permite escribir en: afrikaans, albanés, alemán, catalán, danés, escocés, español, finés, francés, holandés, inglés, islandés, italiano, noruego, portugués, rumano, suaheli, sueco, vasco
  • El conjunto de caracteres ISO8859_2 tiene todos los caracteres de los idiomas europeos centrales: checo, eslovaco, esloveno, polaco, etc.
  • Hay varios ISO8859 más, cada uno de ellos conteniendo los caracteres necesarios para escribir en distintos idiomas europeos
  • Los idiomas del este de Asia no pueden ser codificados con un solo byte ya que esos idiomas tienen muchos miles de caracteres, llamados ideogramas, y en un byte como máximo se pueden tener 256 caracteres. Por ese motivo se necesita de más de un byte para codificarlos
  • Esto implica que la cantidad de caracteres visibles es distinta a la cantidad de bytes necesarios para almacenarlos. En ASCII y en ISO8859 cada carácter ocupa exactamente un byte. En los idiomas de Asia oriental eso no es cierto, ya que cada carácter ocupa varios bytes.
  • Para unificar a todos los conjuntos de caracteres y evitar tantas incompatibilidades se inventó el UNICODE
  • Dentro de UNICODE hay tres posibilidades: UTF-8, UTF-16, UTF-32
  • Con UNICODE se pueden codificar hasta 1.114.112 caracteres distintos, pero la mayoría de ellos aún no están codificados
  • Como se pueden usar hasta 4 bytes por cada carácter lo más sencillo hubiera sido hacer eso, pero el espacio de almacenamiento sería muy grande, ya que para tener todos los caracteres usados por los lenguajes europeos con 2 bytes sería más que suficiente. Es por eso que se inventaron varias formas de codificación, las cuales empiezan con las siglas UTF. Las más usada es la UTF-8
  • Cuando se crea una Base de Datos se puede especificar cual conjunto de caracteres se usará por defecto en ella
  • Si todo el texto que será introducido en las columnas de tipo CHAR o VARCHAR estará escrito en alguno de los idiomas europeos occidentales (el español, entre ellos) usar ISO8859_1. Si existe la posibilidad de que estén escritos en otros idiomas europeos (checo, polaco, ruso, etc.) usar UTF-8.
  • Hasta la versión 2.5.3 el Firebird no dispone de la posibilidad de cambiar el conjunto de caracteres de una Base de Datos. Hay programas utilitarios como el IBEScript que sí tienen esa opción. Con Firebird 3.0 ya se podrá cambiar el conjunto de caracteres

Artículos relacionados:

Entendiendo a los conjuntos de caracteres

Funciones útiles con los conjuntos de caracteres

El índice del blog Firebird21

El foro del blog Firebird21