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