Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Firebird e Interbase (https://www.clubdelphi.com/foros/forumdisplay.php?f=19)
-   -   Nulos y cadenas vacias en Firebird y Delphi (https://www.clubdelphi.com/foros/showthread.php?t=76071)

Quim Herrera 06-10-2011 19:56:32

Nulos y cadenas vacias en Firebird y Delphi
 
Hola compañeros,

Tengo un problema con los nulos y las cadenas vacias en delphi 2009 y firebird 2.5.
Segun tengo entendido un valor nulo es distinto que una cadena vacia. Lo que me desconcierta es el comportamiento de los componentes: Se graba una cosa u otra depende del componente que utilizo.

Supongamos una tabla con:

Código SQL [-]
create table TEST
 ( NCODI         int default 0 not null , 
   CAMPO1     varchar( 15 ) collate ES_ES_CI_AI , 
   CAMPO2     varchar( 15 )  collate ES_ES_CI_AI , 
   CAMPO3     varchar( 15 ) collate ES_ES_CI_AI , 
 CONSTRAINT pk_TEST_NCODI PRIMARY KEY ( NCODI ) );

Utilizando un Tibsql:
Edit1.Text := 'a';
Edit2.Text := 'b';
Edit3.Text := '';

.... insert into TEST (1, Edit1.Text, Edit2.Text, Edit3.Text)
se graba 1, 'a', 'b', '' (cadena vacia)
con lo cual una busqueda
select * from TEST where CAMPO1='a' and CAMPO2='b' and CAMPO3=''
encuentra el registro.

Sin embargo si utilizo TibTable, TIBDataset o un TClientDataset con un TDataSetProvider
al hacer
Dataset.append;
Dataset.Fieldbyname('CAMPO1').asstring := Edit1.Text;
Dataset.Fieldbyname('CAMPO2').asstring := Edit2.Text;
Dataset.Fieldbyname('CAMPO3').asstring := Edit3.Text;
Dataset.post;

se graba 1, 'a', 'b', NULL
Lo que implica que esta convirtiendo la cadena vacia '' en NULL. ¿No hay forma de insertar una cadena vacia en un campo utilizando estos componentes?
Entonces la busqueda
select * from TEST where CAMPO1='a' and CAMPO2='b' and CAMPO3=''
no lo encuentra.

El no saber si va a haber cadenas vacias o nulos me obliga a escribir mucho más código al hacer busquedas:
Lo que seria:
Código Delphi [-]
strwhere := 'CAMPO1='+ quotedstr( Edit1.Text) + 'CAMPO2='+ quotedstr( Edit2.Text) + 'CAMPO3='+ quotedstr( Edit3.Text)
hay que ponerlo como
Código Delphi [-]
if (Edit1.text <> '') and ( Edit2.text <> '') and (Edit3.Text = '') then 
   strwhere := 'where ( CAMPO1= '+ quotedstr( Edit1.Text) + ' and  CAMPO2='+ quotedstr( Edit2.Text) + '   and ( CAMPO3='' or CAMPO3 is NULL )';
if (Edit1.text <> '') and ( Edit2.text = '') and (Edit3.Text = '') then 
   strwhere := 'where ( CAMPO1= '+ quotedstr( Edit1.Text) + ' and  ( CAMPO2='' or CAMPO2 is NULL )   and ( CAMPO3='' or CAMPO3 is NULL )';
if (Edit1.text = '') and ( Edit2.text = '') and (Edit3.Text = '') then 
   strwhere := ( CAMPO1='' or CAMPO1 is NULL ) and ( CAMPO2='' or CAMPO2 is NULL ) and ( CAMPO3='' or CAMPO3 is NULL )
La otra opción es forzar siempre a nulos al grabar pero tambien tengo que escribir más código:
Utilizando un Tibsql:
if (Edit1.text <> '') and ( Edit2.text <> '') and (Edit3.Text = '') then
.... insert into TEST (1, Edit1.Text, Edit2.Text, null)
if (Edit1.text <> '') and ( Edit2.text = '') and (Edit3.Text = '') then
.... insert into TEST (1, Edit1.Text, null, null)
if (Edit1.text = '') and ( Edit2.text = '') and (Edit3.Text = '') then
.... insert into TEST (1, null, null, null)


¿Hay alguna otra forma de solucionarlo?


Saludos y gracias de antemano

Quim Herrera

mightydragonlor 06-10-2011 20:53:56

entonces pregunta en FB que si llega un '' ponga un NULL en esa variable de entrada y ya.

RONPABLO 06-10-2011 21:30:38

Tal vez con un coalesce te puedas mover mejor a la hora del where, eso si, de esta forma no habrá distinción entre null y espacios vacios.

Código SQL [-]
strwhere := 'coalesce(CAMPO1,'')='+ quotedstr( Edit1.Text) + .....

oscarac 06-10-2011 21:56:49

o podrias usar la funcion isnull

Código SQL [-]
Select Campo1, campo2, campo3, isnull(campo3,'') from...

ecfisa 06-10-2011 22:01:49

Hola Quim Herrera.

El comportamiento del TIBDataSet y TIBQuery está reportado aquí, y aquí la resolución... :rolleyes:

Un saludo.

mightydragonlor 06-10-2011 22:17:05

Cita:

Empezado por oscarac (Mensaje 414806)
o podrias usar la funcion isnull

Código SQL [-]
Select Campo1, campo2, campo3, isnull(campo3,'') from...

ISNULL es de MsSQL, para FB es COALESCE, como dijo el compañero RONPABLO

oscarac 06-10-2011 22:18:45

sorry, no me percate de ese detalle.. pero la idea es la misma :eek::eek:

RONPABLO 07-10-2011 02:44:33

Cabe anotar que IsNull es diferente que el Coalesce, teniendo este ultimo más funcionalidad, por ejemplo con el coalesce yo puedo evaluar mas de un campo o variable, algo así como
Código SQL [-]
... coalesce(Campo1, Campo2, Campo3, 'un valor cualquiera si no hay datos en los campos anteriores') ...

mightydragonlor 07-10-2011 04:42:29

que buen dato ;)

Quim Herrera 07-10-2011 08:43:56

Muchísimas gracias a todos.

Coalesce(campo1, '') resuelve perfectamente mi problema. :)

Un abrazo.

Quim Herrera


La franja horaria es GMT +2. Ahora son las 10:04:11.

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