Error de arithmetic overflow, division by zero, or string truncation, en un SELECT

1 comentario

En ocasiones el contenido de una tabla puede dañarse. Por ejemplo, porque primero grabaste algunas filas con un character set y luego cambiaste el character set de la tabla, por otro que es incompatible.

En tales casos al hacerle un SELECT a esa tabla, podrías ver un mensaje de error como el siguiente:

"Arithmetic overflow or division by zero has occurred.
arithmetic exception numeric overflow or string truncation
cannot transliterate character between character sets"

 

¿Por qué podría ocurrir algo así?

Porque el Firebird no verifica que el nuevo character set sea compatible con el anterior y que todas las filas de la tabla puedan ser traducidas (transliteradas). Eso, porque la tabla puede ser muy grande, tener millones y millones de filas, y hacer esa comprobación podría demorar mucho tiempo. Entonces, es tu responsabilidad asegurarte de que lo que estás haciendo está bien, pero … a veces podrías equivocarte.

¿Qué hacer en este caso?

Una posibilidad es tratar de recuperar todas las filas posibles, aquellas filas que aún pueden ser leídas. Esto puede ser algo tedioso pero … hay que hacerlo.

Podríamos crear una tabla que tenga exactamente la misma estructura que la tabla original, pero vacía, sin datos. Sus datos los iremos insertando por partes.

Ejemplo:

El mensaje de error te aparece luego de mostrarte 782 filas al ejecutar el Listado 1.

Listado 1.

SELECT
   ALU_NOMBRE
FROM
   ALUMNOS

Entonces para ir insertando en nuestra tabla auxiliar por partes podríamos escribir algo como:.

Listado 2.

INSERT INTO ALUMNOS2
   (ALU_NOMBRE)
SELECT
   ALU_NOMBRE
FROM
   ALUMNOS
ROWS
   1 TO 782

Lo que hicimos fue crear una tabla llamada ALUMNOS2 que tiene exactamente la misma estructura que la tabla ALUMNOS y luego le insertamos todas las filas que sabemos que están bien.

Listado 3.

INSERT INTO ALUMNOS2
   (ALU_NOMBRE)
SELECT
   ALU_NOMBRE
FROM
   ALUMNOS
ROWS
   784 TO 99999999

Como sabemos que la fila 783 tiene un error entonces en el Listado 3. salteamos hasta esa fila y nuestro INSERT empezará en la fila 784. Si el SELECT del Listado 3. también nos muestra un mensaje de error entonces vamos cambiando la cantidad del SKIP a 785, 786, 787, etc., hasta que podamos realizar el INSERT exitosamente.

De esta manera, aunque no recuperaremos todas las filas de la tabla ALUMNOS, sí podremos recuperar todas las filas que no tenían problemas.

Artículos relacionados:

El índice del blog Firebird21

El foro del blog Firebird21

 

Error 10061

Deja un comentario

Es una muy buena práctica mirar todos los días el contenido del archivo FIREBIRD.LOG porque en ese archivo veremos todos los problemas que tuvo el Servidor del Firebird.

El archivo FIREBIRD.LOG encontrarás en la misma carpeta donde instalaste al Firebird, por ejemplo en:

C:\ARCHIVOS DE PROGRAMA\FIREBIRD\FIREBIRD_2_5\

Si ves una entrada similar a la siguiente:

POS003 (Client) Wed Jul 20 10:27:53 2016
INET/inet_error: connect errno = 10061
ese número de error 10061 significa que se rechazó la conexión.
¿Por qué se rechazó la conexión?
  • Porque el Servidor del Firebird no está ejecutándose en ese momento
  • Porque el número del puerto de conexión es incorrecto

Si por ejemplo, el Servidor del Firebird está usando el puerto 3051 y no especificaste el puerto 3051 en tu string de conexión, obtendrás ese mensaje de error.

Artículos relacionados:

El índice del blog Firebird21

El foro del blog Firebird21

 

Error SQLSTATE = HY000

Deja un comentario

Si cuando quieres conectarte a una Base de Datos el Firebird te muestra el error SQLSTATE = HY000 eso significa dos cosas:

  1. Que la conexión no se realizó
  2. Que la Base de Datos a la cual quisiste conectarte no la reconoce como una Base de Datos válida

El punto 2. por ejemplo puede ocurrir si quieres conectarte a un backup creado por el programa GBAK. El backup creado por el programa GBAK no puede ser usado directamente por el Firebird, debe ser restaurado usando también para la restauración al programa GBAK.

El error HY000 ocurre cuando el Firebird encontró el archivo pero no encontró una página de cabecera en él.

Artículos relacionados:

Entendiendo las páginas de la Base de Datos

El índice del blog Firebird21

El foro del blog Firebird21

 

Error al ejecutar GSEC

2 comentarios

Como seguramente sabes, el programa GSEC.EXE se utiliza para agregar usuarios, cambiar datos de los usuarios, eliminar usuarios y ver cuales son los usuarios admitidos.

Pero si tienes más de una instancia del Firebird instalada entonces a veces podrías ver una pantalla de error similar a la siguiente:

GSEC1

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

¿Qué significa ese error número 335545106?

Que no puede abrir la Base de Datos en la cual se guardan los nombres y las contraseñas de los usuarios.

En Firebird 2.x el nombre de esa Base de Datos es SECURITY2.FDB y la encontrarás en la misma carpeta donde instalaste al Firebird.

¿Cómo se soluciona ese error?

Si tienes más de una instancia del Firebird instalada entonces cada instancia usa su propio puerto (o así debería ser si se instaló correctamente). Por lo tanto la solución es indicarle que abra el archivo SECURITY2.FDB que corresponde a la instancia que estemos usando en ese momento.

GSEC2

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

Como puedes ver en la Captura 2. se indico la IP de la computadora y el puerto 3050. Como ese es el puerto que le corresponde a la instancia del Firebird que nos interesa, funcionó perfectamente.

Después de la opción -database se escribió la ruta completa entre comillas porque hay un espacio en blanco en el medio, y en esos casos el Windows exige que se usen comillas.

Artículos relacionados:

El índice del blog Firebird21

El foro del blog Firebird21

Error: Too many Contexts of Relation/Procedure/Views. Maximum allowed is 255

1 comentario

Cuando escribes un stored procedure, un execute block, o una view hay un límite a la cantidad de contextos que puedes tener.

¿Qué es un contexto?

Es cualquier comando del Firebird que hace referencia a una tabla (o más de una).

Ese límite es por declaración, no por stored procedure, execute block o view. No hay que confundir.

Las declaraciones posibles son:

  • INSERT
  • UPDATE
  • DELETE
  • SELECT

Ninguna de esas declaraciones puede tener más de 255 contextos. Ese es el límite máximo.

Pero además, cada GROUP BY y cada UNION suma 1 contexto más.

Ejemplos:

  • Un SELECT a una tabla tiene un contexto
  • Un SELECT con un JOIN tiene dos contextos
  • Un SELECT con dos JOIN tiene tres contextos
  • Un SELECT con una subconsulta tiene dos contextos
  • Un SELECT con dos subconsultas tiene tres contextos
  • Un SELECT con una subconsulta y con un JOIN tiene tres contextos
  • Un SELECT autoreferenciado (ambas tablas del JOIN son la misma) tiene dos contextos
  • Un SELECT con un GROUP BY tiene dos contextos
  • Un INSERT que referencia a una view, tiene un contexto por cada tabla que es referenciada en la view
  • Un UPDATE que referencia a una view, tiene un contexto por cada tabla que es referenciada en la view

Cada INSERT, cada UPDATE y cada DELETE suma 2, por las seudo-variables NEW y OLD de los triggers. En los demás casos se suma 1.

La cantidad máxima de contextos que puedes tener (hasta la versión Firebird 3.0) es de 255, si superas esa cantidad entonces verás el mensaje de error que da título a este artículo.

Listado 1.


SELECT <mis_columnas_1> FROM MiTabla1;

UNION

SELECT <mis_columnas_2> FROM MiTabla2;

En el Listado 1. hay 3 contextos.

Listado 2.


INSERT INTO MiTabla <mis_columnas> VALUES <lista_valores>;

INSERT INTO MiTabla <mis_columnas> VALUES <otros_valores>;

En el Listado 2. el primer INSERT tiene 2 contextos y el segundo INSERT también tiene 2 contextos. Esos contextos no se suman, cada uno de ellos es independiente, porque lo que vale es la cantidad de contextos que cada declaración tiene.

Solución:

Si el Firebird te muestra este mensaje de error entonces tienes que disminuir la cantidad de contextos. Eso puedes hacerlo de varias maneras, por ejemplo usando una tabla CTE en lugar de varias subconsultas, o cambiando la condición de filtro del WHERE, o disminuyendo la cantidad de JOIN, etc.

Artículos relacionados:

El índice del blog Firebird21

El foro del blog Firebird21

ERROR: Connection rejected by remote interface

5 comentarios

Si ves este mensaje (la conexión fue rechazada por la interface remota) la consecuencia es que el usuario no puede conectarse a la Base de Datos.

Un posible motivo es que está usando un cliente de InterBase en lugar de usar un cliente de Firebird.

Artículos relacionados:

El índice del blog Firebird21

El foro del blog Firebird21

Error 802 en una consulta

1 comentario

En el foro preguntaron:

¿Por qué esta consulta:

Listado 1.

SELECT
   192.76110000000000 / 2.2200
FROM
   RDB$DATABASE

muestra el error: -802 Arithmetic overflow or division by zero has occurred.?

El problema, tal y como se explicó en el artículo Usando NUMERIC y DECIMAL es debido a la forma en que el Firebird define a los números escalados (también llamados de coma fija o de punto fijo; son sinónimos).

En Firebird los números escalados tienen el formato:

p.s

donde p indica la precisión y s indica la escala (s=scale, en inglés).

La precisión máxima en Firebird, hasta la versión 2.5.4 es de 18. La escala siempre debe ser menor o igual a la precisión, nunca puede ser mayor.

¿Cuál es la precisión del resultado cuándo se hace una división?

Siempre es 18.

¿Cuál es la escala del resultado cuándo se hace una división?

Siempre es la suma de la escala del numerador más la escala del denominador.

¿Cuál fue el problema en la división que dio origen a este artículo?

Que el numerador (192.76110000000000) tiene una escala de 14 y el denominador (2.2200) tiene una escala de 4. El resultado de la división por lo tanto tendrá una escala de 18 (es decir, 14 + 4). Ya está en el límite máximo permitido.

La división anterior sí funcionará si la parte entera del numerador es pequeña, por ejemplo:

Listado 2.

SELECT
   19.76110000000000 / 2.2200
FROM
   RDB$DATABASE

La parte entera del numerador es 19 y allí sí funciona.

¿Por qué funciona cuándo el numerador es pequeño?

Si la precisión es 18 entonces el número se guarda como un BIGINT. Los números de tipo BIGINT pueden encontrarse entre -2 * 10 ^ 63 y 2 * 10 ^ 63 – 1. O sea, entre -9.223.372.036.854.775.808 y +9.223.372.036.854.775.807

Si la escala es 18 entonces el Firebird divide a ese número por 1.000.000.000.000.000.000 o sea un 1 seguido por 18 ceros.

Al dividir 9.223.372.036.854.775.807 por 1.000.000.000.000.000.000 obtenemos: 9,223372036854775807

Por lo tanto, si la precisión es 18 y la escala es 18 (como en el Listado 1.) el resultado de la división debe ser 9,22 ó menor para no obtener un error de overflow.

Pero en el Listado 1. el resultado de la división es 86,829321…., ese número es mayor que 9,22 y entonces lo que se obtiene es un … error de overflow.

¿Y si necesitamos hacer sí o sí la división del Listado 1., cómo lo solucionamos?

Tenemos varias alternativas:

Listado 3.

SELECT
   192.7611 / 2.2200
FROM
   RDB$DATABASE

Le quitamos los ceros al numerador y funciona sin problemas porque ahora la escala es de 8.

Listado 4.

SELECT
   192.76110000000000 / 2.22
FROM
   RDB$DATABASE

Le quitamos los ceros al denominador y funciona sin problemas porque ahora la escala es de 16.

Listado 5.

SELECT
   CAST(192.76110000000000 AS NUMERIC(18, 13)) / 2.2200
FROM
   RDB$DATABASE

Empleamos la función CAST() para disminuir la escala del numerador y funcionó sin problemas.

Listado 6.

SELECT
   CAST(192.761100000000000 AS FLOAT) / 2.2200
FROM
   RDB$DATABASE

Empleamos la función CAST() para cambiar el tipo de datos del numerador a FLOAT y funcionó sin problemas.

Conclusión:

Tal y como se dijo en el artículo antes citado: “La precisión del resultado siempre es 18. La escala del resultado es la suma de las escalas del dividendo y del divisor. Esto implica que la escala del cociente siempre será mayor que las del dividendo y del divisor. Debes tener cuidado con esto si los números que empleas tienen muchos decimales o podrías sobrepasar la escala máxima que es 18 o necesitar una precisión mayor que 18 y en ambos casos eso te ocasionaría un error de overflow.”

Lo importante a recordar aquí por lo tanto es que si divides números que tienen muchos decimales puedes sobrepasar la escala máxima de 18 o necesitar una precisión mayor que 18 y en ambos casos tendrás un error de overflow.

Hay varios métodos para realizar la división de todos modos, algunos de los cuales vimos en los últimos listados de arriba (hay varios más, pero ya tienes la idea).

Artículos relacionados:

Usando NUMERIC y DECIMAL

El índice del blog Firebird21

El foro del blog Firebird21

Older Entries