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