PDA

Ver la Versión Completa : Poner 0 cuando el resultado en null


victork_py
20-06-2003, 23:59:08
Hola a todos, tengo una consulta que me devuelve algunos campos numéricos, pero en algunos casos los campos numéricos estan nulos, y en ese caso, quiero que el resultado sea 0, y no Null.
Es posible?

Desde ya, muchas gracias

jachguate
21-06-2003, 00:04:55
desde donde, desde delphi, desde isql, desde un stored procedure, desde donde????

victork_py
21-06-2003, 01:03:07
De la consulta SQL, pongo un ejemplo:

select monto from tabla:

en este caso, si el campo monto esta nulo, el SQL devuelve <null>, y lo que yo quiero es que me devuelva 0.

No me acuerdo como se llama la función, pero en ORACLE existe una función que te hace esto. Lo que quiero saber es si en Firebird se puede hacer algo similar.

Una solución que tengo es asignarle 0 como valor por defecto del campo, pero si es posible no quiero modificar la tabla y solucionarlo en mi consulta.

delphi.com.ar
21-06-2003, 01:10:30
En Oracle es NVL
En SqlServer es ISNULL
En Access es NZ


Desconozco en Interbase/Firebird, pero si no existe no creo que sea complicado crearla.

Saludos!

jachguate
21-06-2003, 01:23:31
En interbase hasta la versión 6 no la hay.... quizas en la versión 7 o en firebird 1.5....

como extraño al Decode de oracle también....


De cualquier forma podes hacerte una pequeña dll que te de la funcionalidad....

hasta luego.

;)

chutipascal
21-06-2003, 14:45:41
Puede ser que haya otras soluciones, pero una forma de hacerlo puede ser esta:

Primero defines la funcion externa DIV

DECLARE EXTERNAL FUNCTION DIV
INTEGER, INTEGER
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'IB_UDF_div' MODULE_NAME 'ib_udf';


Despues en la consulta de por ejemplo esta tabla

Tabla de ejemplo
CREATE TABLE "MONEDAS"
(
"COD_MON" INTEGER NOT NULL,
"CVN_MON" INTEGER
);


CVN_MON tendria algunos nulos que quieres transformar a 0
para eso usas la función DIV (división sin resto) igualando el divisor a 1.


select cod_mon, DIV(cvn_mon,1) from monedas;

Ohhh funciona!
De ese modo tiene el nullo transformado a 0.......

Recuerda es un apaño y solo funciona con enteros lo ideal seria tener una función externa para eso.
Si quieres que funcione con 2 decimales puedes hacer algo por el estilo. por ejemplo si CVN_MON fuera NUMERIC(8,2) por ejemplo.
usa esto:
(DIV(cast ((cvn_mon * 100) as integer),1))/100

>>Recuerda comentar profusamente esta sentencia por si alguien viene detras de ti para que pueda entender el porque....

victork_py
23-06-2003, 18:05:23
Muchas gracias a todos, al final he solucionado creando una dll.

jachguate
24-06-2003, 07:03:09
evidentemente la función div comentada por chutipascal tiene un bug... pues al operar sobre un null deviera devolver null??

al menos a mi me parece que debiera ser así...

;)

Kafu
24-06-2003, 10:35:11
al operar sobre un null deviera devolver null??

Yo también pienso lo mismo, aunque no estoy seguro. Otra solución que se me ocurre es hacer una union entre dos consultas, una la que devuelve nulos y otra que no. y en la parte que devuelve null poner 0 en lugar del campo. Algo como:

Select campo1, campo2 from tabla where not campo1 is null
union
select 0, campo2 from tabla where campo1 is null

Un saludo,




F.T.G.

chutipascal
24-06-2003, 10:43:39
Si evidentemente, se puede pensar de que es un bug o de que se trata de una 'caracteristica del sistema' por eso aconsejo de comentar profusamente una sentencia construida de esa forma, por cierto me gusta mucho la sentencia de kafu.

Un saludo.

emili
24-06-2003, 11:51:15
Otra alternativa es tomar como política el no tener ningún campo integer o float en la BD con valor null.

Es decir, siempre que vamos a grabar podemos utilizar un procedimiento como este:


Nullsazero(Ttable(dataset)); // =Nullsazero(Tproveedores);


Procedure Nullsazero(Taula:Ttable);
var i:smallint;
begin
For i:=0 to taula.FieldCount-1 do
begin
If ((Taula.Fields[i].Datatype=ftfloat) and
(Taula.Fields[i].Isnull)) then
Taula.Fields[i].AsFloat:=0;
If (((Taula.Fields[i].Datatype=ftsmallint) or
(Taula.Fields[i].Datatype=ftinteger)) and
(Taula.Fields[i].Isnull)) then
Taula.Fields[i].AsInteger:=0;
end;
end;


Igual parece pesado cada vez tener que invocar al procedimiento, pero si tenemos la aplicación bien diseñada, podemos tener un "form base" de los que todos los otros heredan, y la invocación a NullsAZero solo la hará éste form base, y no lo tendremos que incluir en todos los forms que vamos creando.

Saludos!
:)

chutipascal
26-06-2003, 12:42:47
Posteado originalmente por emili
Otra alternativa es tomar como política el no tener ningún campo integer o float en la BD con valor null.

Para tener el mismo efecto es suficiente poner not null default 0 en la definición de la tabla.
De todas formas el (null) es necesario en algunos casos, tiene el significado de que no hay dato para ese campo cosa muy distinta a que tenga un cero.


Un saludo.

jachguate
26-06-2003, 13:23:39
Es un hecho que en ocasiones los campos a null son necesarios. De hecho, por eso existe la posibilidad de poner los campos a null, y yo creo personalmente que es una deficiencia de Interbase no contar con una función al estilo de la nvl() de oracle.

Sin embargo, también es fácil hacer una dll que cubra esa función. Lo que no es bueno es que no hay una estándarización para la forma de hacerlo, y eso al final de cuentas, impide que la comunidad de firebird se vuelva más sólida. Lo digo porque regularmente si queres integrar a alguna persona a tu equipo de desarrollo, no basta con que sepa firebird... sino que tiene que aprender la forma de hacer una y mil cosas. Además cuando vos te vas a integrar a otro equipo de desarrollo, o tenes que agarrar una aplicación ya desarrollada en interbase, es una cantidad de cosas que aprender que elevan los tiempos y los costos...

en fín... ese ya es tema de un debate y no de esta conversación.

Hasta luego.

;)

kinobi
26-06-2003, 14:00:13
Hola,

Posteado originalmente por jachguate
Lo que no es bueno es que no hay una estándarización para la forma de hacerlo, y eso al final de cuentas, impide que la comunidad de firebird se vuelva más sólida.

pero eso es un problema de todos los motores relacionales. En la maraña de comités de estandarización de los organismos internacionales, especialmente ANSI en el caso de las bases de datos relaciones, se fijan una serie de modelos de referencia y normas que los productores de software pueden seguir libremente, aunque en general sólo lo hacen de forma parcial.

Toma el ejemplo de las normas estándar para el SQL, casi todas las compañías dicen cumplirlas y seguir alguno de los estándares: SQL-92, SQL-99, ..., pero en general sólo lo hacen al nivel básico (entry-level) y muy parcialmiente a nivel medio y avanzado. Y esto es común en todos los productos, incluidos los más conocidos: Oracle, MS-SQL Server, InterBase ...

La cuestión es que empresas como Oracle o Microsoft pueden desviarse del estándar y crear un estándar (no-oficial) de facto, debido a la gran penetración que tienen en el mercado, cosa que es prácticamente imposible para productos como InterBase. Otra cuestión es aceptar un estándar propietario sobre otro elaborado por un organismo independiente (y no todos los organimos que se dicen independientes lo son).

Saludos

chutipascal
26-06-2003, 14:19:09
Y ademas en la variedad esta el gusto, personalmente no me alegraria de tener un panorama como la china de mao (todos vestidos con el mismo uniforme), el que las prestaciones y otras cosas sean distintas te permite.... elegir

Un saludo.

jachguate
26-06-2003, 15:02:21
Por supuesto... estoy totalmente de acuerdo entre ustedes...

Cuando me referia al problema de la falta de "estandarización" me referia a que existiera una función estándar dentro de interbase, por ejemplo, para convertir un valor nulo en uno arbitrario, que siempre se presenta el caso:

les doy un ejemplo.

En oracle yo puedo hacer algo como:



Select nvl(Nombre, 'Sin Nombre')
from clientes;

o

Select nvl(saldo, 0)
from saldo;


cuando no quiera null's... cuando pueda dejar pasar los nulls, pues no le pongo nvl's y ya.

y cualquier persona que conozca oracle entenderá mis query's, sabrá exactamente lo que quise hacer y podrá modificarlos, lo que no ocurre con interbase, al menos en una función tan Vital.

Además, le agrega un poder por defecto a la base de datos....

;)

kinobi
26-06-2003, 15:46:41
Hola,

Posteado originalmente por jachguate
Cuando me referia al problema de la falta de "estandarización" me referia a que existiera una función estándar dentro de interbase, por ejemplo, para convertir un valor nulo en uno arbitrario, que siempre se presenta el caso:

pero precisamente esa (hipotética) "función estándar" que comentas estaría fuera del estándar (el estándar oficial, el de ANSI, no el que imponen compañías como Oracle o Microsoft), ya que un operando NULL en una expresión convierte a ésta en nula (NULL), sea cuál sea el operador.

En resumen, o el estándar está mal especificado (operando NULL --> expresión NULL) o el uso de funciones tipo nvl de Oracle no puede formar parte del estándar, ya que es un atajo para saltarse la norma. Advierte que no estoy cuestionando la necesidad ni la utilidad de la función, sino si ésta debe ser implantanda, de forma estándar, en todo motor relacional.

Saludos

jachguate
26-06-2003, 16:20:20
Hola.

Posteado originalmente por kinobi
pero precisamente esa (hipotética) "función estándar" que comentas estaría fuera del estándar (el estándar oficial, el de ANSI, no el que imponen compañías como Oracle o Microsoft), ya que un operando NULL en una expresión convierte a ésta en nula (NULL), sea cuál sea el operador.


Por supuesto que entiendo cual es tu punto... y entiendo que está fuera de cualquiera de los estándares de la ANSI.

Sin embargo, creo que lo que hace fuertes también a las bases de datos no solo es su apego a las normas estándares, sino las prestaciones adicionales que pueden ofrecerte. Quizás he empleado mal el término... y no quiero discutir con Kinobi acerca de estándares, ya que nunca los he leido..... así que fácilmente metere la pata.

Pero en mi escritorio, cuando estoy programando, agradezco ciertos "atajos" que al final de cuentas me hacen mas fácil la vida y me vuelven mas productivo. Es una apreciación personal.

Hasta luego.

;)

kinobi
26-06-2003, 17:59:40
Hola,

Posteado originalmente por jachguate
Sin embargo, creo que lo que hace fuertes también a las bases de datos no solo es su apego a las normas estándares, sino las prestaciones adicionales que pueden ofrecerte.
Cierto, estoy de acuerdo con esa apreciación. Mi comentario iba en el sentido de que esas prestaciones adicionales son propias y exclusivas de cada motor particular y, por tanto, no forman parte del común denominador que soportan todos los motores relacionales, eso que llamamos estándar. Otra cuestión, como apunté en el mensaje anterior, es que el estándar pueda estar mal definido y esa prestación de ciertos implantaciones particulares tal vez debiera estar contemplada en el estándar común.

Posteado originalmente por jachguate
Pero en mi escritorio, cuando estoy programando, agradezco ciertos "atajos" que al final de cuentas me hacen mas fácil la vida y me vuelven mas productivo.

También estoy de acuerdo, aunque convendrás conmigo que tomar esos atajos supone asumir riesgos de cara al futuro: un cambio de producto, nuevos desarrolladores, ... Todo proyecto software tiene una evaluación de riesgos de ese tipo (y otros muchos), si éstos son asumibles, no hay razón para no tomar esos atajos; sabiendo, eso sí, que los riesgos están ahí y que existen planes de contingencia por si surgen los problemas.

Saludos

ariels
29-07-2003, 15:04:06
Hola,
Siguiendo el tema, me parece que a lo que se refiere jachguate, es que sería bueno que dentro de Interbase haya un "estandar" para realizar esta conversión y no tener que cada desarrollador implementear una solución particular. Sin necesidad de que esa solución sea el estandar de ANSI, se entiende?. Asi como SQL Server tiene el ISNULL u Oracle el NVL, Interbase deberia tener "algo".
Es simplemente una apreciación al seguir el hilo.
Saludos.
Ariel.

guillotmarc
29-07-2003, 19:54:01
Hola.

Firebird 1.5 soporta la sintaxis de Oracle y SQL Server : ISNULL, COALESCE, NVL, ...

Para Firebird 1.0 yo utilizo una udf estándar en lugar de crear mi propia librería. En concreto utilizo la fbudf que viene con el propio firebird. Tiene funciones para distintos tipos, por ejemplo la INVL es para enteros :


DECLARE EXTERNAL FUNCTION INVL
INTEGER BY DESCRIPTOR,
INTEGER BY DESCRIPTOR
RETURNS INTEGER
ENTRY_POINT 'idNvl' MODULE_NAME 'fbudf'


Saludos.

victork_py
18-08-2003, 22:39:00
Hola guillotmarc, después de mucho tiempo, pensé usar la función INVL que comentas y lo declaré en la base de datos con la misma sentencia que publicaste.
Cuando ejecuto el DECLARE EXTERNAL FUNCTION, no me salta ningún error, pero cuando trato de usar la función INVL en mi sentencia SELECT, me salta el siguiente error:

Invalid data type, length, or value

aún cuando el campo que le paso es de tipo INTEGER.

Por que podrí ser eso?

IVAND
09-09-2003, 03:58:47
Hola a todos

Le comento que existen unas Udf que implantan varias funciones importantes entre ellas la de convertir Null a 0

Y la funcion se llama Z

Estas udf se las puede bajar desde

?? O por el momento no me recuerdo pero si usan un buscador con las palabras rFunc de seguro las encuentran

Y si no me escriben de seguro ya he de tener la direccion


:D

juanfergl
19-04-2014, 05:36:05
hola, si dentro del form estas recibiendo los datos a un RxmemoryData, o algun otro ClientDataset, este al llenar los datos hara la conversion de manera automatica para los campos numericos, y asi no tentras que preocuparte por ello.Es decir si el campo es numerico en la BD dentro del maitable lo dejara como 0.

Casimiro Notevi
19-04-2014, 10:53:26
11 años después.