Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Otros temas > Trucos
Registrarse FAQ Miembros Calendario Guía de estilo Buscar Temas de Hoy Marcar Foros Como Leídos

Los mejores trucos

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 01-07-2006
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 13.107
Poder: 34
dec Tiene un aura espectaculardec Tiene un aura espectacular
Los tipos numéricos de Interbase

Mi objetivo es mostrarle al lector qué es lo que sucede realmente en InterBase cuando utilizamos los tipos numeric y decimal de SQL estándar. Podemos utilizar estos tipos en la declaración de columnas de tablas, en la creación de dominios, en variables locales y en parámetros de procedimientos almacenados. La principal peculiaridad de ambos consiste en que podemos adjudicarles una precisión y una escala. La precisión es el número de dígitos, tanto a la derecha como a la izquierda de la coma decimal, que se pueden representar mediante el tipo. De esa cantidad, la escala roba unos cuantos dígitos para que se coloquen a la derecha de la coma. Por supuesto, la escala debe ser siempre menor o igual que la precisión:

Código SQL [-]
create tabla Empleados (
   Codigo     numeric(9) not null,     /* Lo mismo que numeric(9,0) */
   Peso       numeric(6,3),            /* Peso en kilogramos y gramos */
   Patrimonio numeric(15,2),
   /* ... */
);

En la actual implementación de InterBase, numeric y decimal son totalmente equivalentes. La precisión máxima permitida actualmente es de 15 dígitos, pero probablemente cambie en futuras versiones.

Cuando un programador proveniente de xBase ve estos tipos los asocia inmediatamente con el tipo numérico de dBase. En este sistema los valores numéricos se representan en formato ASCII (todo un despilfarro), y está claro que es importante especificar un tamaño máximo para ahorrar espacio. Por lo tanto, este programador hará un uso intensivo de numeric. ¿Hace bien o mal? Le explico lo que hace InterBase, y ya usted decidirá.

Sorpresa número uno: Desde el punto de vista del espacio ocupado para su almacenamiento, las dos columnas siguientes son iguales:

Código SQL [-]
   /* ... */
   Altura   numeric(3,2),
   Peso     numeric(4,2),
   /* ... */

Lo que sucede es que InterBase elige siempre uno de los tres tipos siguientes para representar físicamente el valor: smallint, integer o double precision. La elección está determinada por la precisión especificada, y se ignora la escala:

Precisión Tipo base Espacio necesario

Código:
1..4 SMALLINT 2 bytes
5..9 INTEGER 4 bytes
10..15 DOUBLE PRECISION 8 bytes
¿Y qué pasa con la escala? Si definimos una columna como numeric(3,2), por ejemplo, sus valores se almacenan multiplicados por 100, para obtener un número entero. La escala se guarda en una tabla del sistema, y se utiliza para restaurar el número original durante la evaluación de expresiones por InterBase. Si, por el contrario, la precisión es superior a 9, el número se almacena directamente con el formato de double precision, como ya he dicho. Este tipo se representa con 8 bytes, y puede contener sin dificultad alguna los 15 dígitos de precisión mencionados.

Sorpresa número 2: El BDE tiene problemas para trabajar con los tipos de campos anteriores, especialmente cuando la precision es menor que 10. Cuando traemos un campo numérico a Delphi y la configuración del BDE es la implícita, se crean objetos de tipo TIntegerField o TFloatField, de acuerdo a la precisión. Por supuesto, en un campo entero se truncarán los decimales o, en versiones anteriores del BDE, el número aparecerá multiplicado por el factor de escala. Y los campos TFloatField ignorarán el número de dígitos decimales, mostrando cuantos decimales estimen pertinentes.

Una solución consiste en activar el parámetro ENABLE BCD en la configuración del alias del BDE. En tal caso, siempre se traen campos TBCDField, que utilizan el tipo Currency internamente para almacenar los valores. Sin embargo, estos campos tienen una limitación: solamente pueden representar hasta 4 dígitos decimales. Así que no abuse de ellos.

Finalmente, ¿está preparado para la Sorpresa número 3? Resulta que para InterBase los siguientes tipos no solamente se representan del mismo modo, ¡sino que son indistinguibles entre sí!

Código SQL [-]
   /* ... */
   Columna1   numeric(5,2),
   Columna2   numeric(8,2),
   /* ... */

Esto sucede porque InterBase no almacena en las tablas de sistema la precisión, sino solamente el factor de escala más el tipo base elegido para representarlos. Los dos tipos anteriores son idénticos a numeric(9,2). El tipo numeric(5) es indistinguible respecto a un integer. Si quiere comprobarlo, llame al SQL Explorer, abra un alias de InterBase y ejecute la siguiente instrucción SQL:

Código SQL [-]
create domain DomPrueba as numeric(5,2)

Ahora sitúese en la rama del árbol de la izquierda correspondiente a los dominios, y pulse Ctrl+R para actualizar el árbol. Seleccione el nodo DomPrueba y en el panel de la derecha active la pestaña Text. Posiblemente le sorprenda ver que InterBase "cree" que la definición del dominio es:

Código SQL [-]
CREATE DOMAIN DomPrueba AS
  NUMERIC(9,2)

Si lo desea, puede ejecutar también la siguiente consulta:

Código SQL [-]
select *
from   RDB$FIELDS
where  RDB$FIELD_NAME = 'DOMPRUEBA'

Observe entonces que la columna rdb$field_length contiene sencillamente el valor 4, que corresponde a un entero, y que no hay más información sobre la precisión utilizada en la definición.

¿Conclusiones? Estas son las mías:

No merece la pena especificar una precisión y escala para columnas numéricas, pues InterBase siempre utilizará uno de sus tipos binarios nativos para representarlas. Tampoco merece el esfuerzo utilizar precisión y escala si lo que necesitamos es restringir el rango de valores admitidos por la columna. Como hemos visto, dentro de cierto intervalo de valores de precisión, InterBase es incapaz de distinguir entre ellos. Si quiere limitar un rango de valores utilice cláusulas check.
Responder Con Cita
Respuesta


Herramientas Buscar en Tema
Buscar en Tema:

Búsqueda Avanzada
Desplegado

Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro


La franja horaria es GMT +2. Ahora son las 23:26:03.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi