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)
-   -   Consulta con valores null (https://www.clubdelphi.com/foros/showthread.php?t=77961)

Luis M. 08-03-2012 21:54:57

Consulta con valores null
 
Saludos.

Trabajo con D2007 y FB 2.5.
Tengo la siguiente consulta:
Código Delphi [-]
DMList.QApuntes.Close;
DMList.QApuntes.SQL.Text := 'Select * From Apuntes Where (familia >= '+
                             QuotedStr(DesdeFamilia.Text)+') and (familia <= '+
                             QuotedStr(HastaFamilia.Text)+')';
DMList.QApuntes.Open;

En la tabla Apuntes, en el campo Familia hay almacenados valores null.
DesdeFamilia y HastaFamilia son componentes Edit.
Si dejo DesdeFamilia en blanco (no entro ningún valor)
La consulta anterior me devuelve todos los valores almacenados menos los null.
¿Cual sería la consulta correcta para que me diese todos los registros encontrados dentro del rango
DesdeFamilia - HastaFamilia?

Gracias por su ayuda.

kapcomx 09-03-2012 00:25:48

null
 
tal vez si intentas con un if

if (desdefamilia.text='') then beginDMList.QApuntes.Close;DMList.QApuntes.SQL.Text := 'Select * From Apuntes Where (familia = null)';DMList.QApuntes.Open;
end
else
begin

DMList.QApuntes.Close;DMList.QApuntes.SQL.Text := 'Select * From Apuntes Where (familia >= '+ QuotedStr(DesdeFamilia.Text)+') and (familia <= '+ QuotedStr(HastaFamilia.Text)+')';DMList.QApuntes.Open;

end;


en mysql uso Familia is null no se si sea igual en fb 2.5 o no se si en fb2.5 sea correcto poner familia=null :cool:

Casimiro Notevi 09-03-2012 00:48:45

Por favor, no olvidar las etiquetas de código, ejemplo:



.

kapcomx 09-03-2012 01:02:37

disculpas
 
Tienes Razon casimiro, como se me fue a olvidar jejejeje:cool:

que tal vez si intentas con un if
Código Delphi [-]
 

if (desdefamilia.text='') then 
begin
DMList.QApuntes.Close;DMList.QApuntes.SQL.Text := 'Select * From Apuntes Where (familia = null)';
DMList.QApuntes.Open;
end
else
begin

DMList.QApuntes.Close;DMList.QApuntes.SQL.Text := 'Select * From Apuntes Where (familia >= '+ QuotedStr(DesdeFamilia.Text)+') and (familia <= '+ QuotedStr(HastaFamilia.Text)+')';DMList.QApuntes.Open;

end;

MartinS 09-03-2012 12:04:09

Tal vez no entiendo muy bien lo que necesitas en caso de que no existan valores en los TEdit. Por lo que veo la consulta expuesta por el compañero kapcomx muestra o los null o los del rango de acuerdo al contenido del Edit si esta vacio o no. Si lo que deseas es que muestre en conjunto el rango + los null deberias agregar a la consulta

Código Delphi [-]
and (familia is null)

y si... la forma es igual que en mysql (is null).-

Saludos

Chris 09-03-2012 15:58:23

Una cosa importante a tener en cuenta:

NULL es NULL. NULL es un valor indefinido según el estándar SQL. Al ser indefinido, NULL no es ni mayor ni menor a `''´ ni tampoco es igual. NULL es un valor único que solo es similar a NULL. Si lo que quieres es devolver opcionalmente los valores NULL tendrás que indicarlo en la consulta. Por ejemplo:
Código SQL [-]
Select * From Apuntes Where (familia between :familia_start and :familia_end) or (familia is NULL)

Ten en cuenta que el operador indicado para trabajar con NULL es `is´. NULL es tan especial que los demás operadores no son recomendados para trabar con él.

Saludos!

ecfisa 09-03-2012 16:05:37

Hola Luís.

Otra opción:
Código Delphi [-]
 with QApuntes do
  begin
    Close;
    SQL.Clear;
    SQL.Add('SELECT * FROM APUNTES ');
    SQL.Add('WHERE FAMILIA >= :DESDE AND FAMILIA <= :HASTA OR FAMILIA IS NULL');
    ParamByName('DESDE').AsString:= DesdeFamilia.Text;
    ParamByName('HASTA').AsString:= HastaFamilia.Text;
    Open;
  end;

Saludos.

Edito: No había visto el mensaje de Chris, así que corrijo "Otra opción" por 'Una opción parecida' ... :)

Luis M. 09-03-2012 18:55:02

Saludos.

Ante todo dar las gracias a todos los que habéis respondido.
Chris tiene toda la razón, Null es Null y el único operador para trabajar con él, es IS.
He probado todas las opciones que me habéis recomendado y no me funcionaba con yo quería.
O no me devolvía ningún registro o me devolvía todos menos los null.
Así que con la idea de kapcomx y del resto de compañeros, he podido solucionar el problema.
Código Delphi [-]
  if DesdeFamilia.Text = '' then cConsulta := '(familia <= '+QuotedStr(HastaFamilia.Text)+') or (Familia is null)'
  else cConsulta := '(familia >= '+QuotedStr(DesdeFamilia.Text)+') and (Familia <= '+QuotedStr(HastaFamilia.Text)+')';
Código Delphi [-]
DMList.QApuntes.Close;
DMList.QApuntes.SQL.Text := 'Select * From Apuntes Where '+cConsulta;
DMList.QApuntes.Open;

Ahora ya me devuelve los registros dentro del rago y si "Desdefamilia" está vacío me devuelve los null.
Espero que a otros le sirva de ayuda.
Nuevamente gracias a todos por vuestra ayuda.

Casimiro Notevi 09-03-2012 19:03:13

¿Y no puedes poner todos los campos null a cadena vacía?

Código SQL [-]
update apuntes set familia='' where familia is null

Se acabó el problema.

RONPABLO 09-03-2012 21:20:46

Esto podría funcionar.
Código Delphi [-]
DMList.QApuntes.Close; DMList.QApuntes.SQL.Text := 'Select * From Apuntes Where (coalesce(familia,'') >= '+
                              QuotedStr(DesdeFamilia.Text)+') and (coalesce(familia,'') <= '+
                              QuotedStr(HastaFamilia.Text)+')'; 
DMList.QApuntes.Open;

Luis M. 09-03-2012 21:48:06

Cita:

Empezado por Casimiro Notevi (Mensaje 427252)
¿Y no puedes poner todos los campos null a cadena vacía?

Código SQL [-]
update apuntes set familia='' where familia is null

Se acabó el problema.

Hola Casimiro.
Fue lo primero que intenté.
En el OnNewRecord del Dataset intenté con ApuntesFamila.asstring := '', también ApuntesFamilia.asstring := ' ' pero si me iba al IBExpert para comprobar los datos, allí estaba ese lindo null .
También lo intenté en el BeforePost con
Código Delphi [-]
if ApuntesFamilia.isnull then ApuntesFamilia.asstring := '', etc.
pero de nada servia.
No he echo lo que me recomiendas, lo intentaré a ver que tal.
RONPABLO hoy no me da tiempo para probarlo, en cuanto lo haga te digo si funciona.
Un saludo para todos.

Casimiro Notevi 09-03-2012 22:27:17

Cita:

Empezado por Luis M. (Mensaje 427269)
Hola Casimiro.
Fue lo primero que intenté.
En el OnNewRecord del Dataset intenté con ApuntesFamila.asstring := '', también ApuntesFamilia.asstring := ' ' pero si me iba al IBExpert para comprobar los datos, allí estaba ese lindo null .
También lo intenté en el BeforePost con Código Delphi [-]if ApuntesFamilia.isnull then ApuntesFamilia.asstring := '', etc.

pero de nada servia.

Pero es que no es eso lo que te he dicho :)

De todas formas, si quieres grabar algo tendrás que hacerlo en la BD, no dando un valor a un componente, o sea:

Código Delphi [-]
beforepost

if tabla.campo is null then
  tabla.campo := '';

Luis M. 10-03-2012 14:22:19

Hola Casimiro.
Te entendí perfectamente y creo que es la mejor solución.
Código Delphi [-]
update apuntes set familia='' where familia is null
Igualmente te comento que "ApuntesFamilia" es un campo persistente por eso le daba el valor '' si era null.
Pero no funcionaba.
Algo debía de estar trastocado porque me iba al IBExpert y le ponía manualmente un espacio en blanco al campo null y me lo volvía a dejar en null.
Ahora parece que ya funciona.
Esto de los valores null tiene su tela.
Un saludo para todos y gracias.

guillotmarc 10-03-2012 19:32:23

Hola.

Utiliza la función COALESCE de Firebird, con la que le indicas que si el campo es nulo, entonces considere otro valor (pasado como segundo parámetro).

Es decir :

Código Delphi [-]
DMList.QApuntes.Close;
DMList.QApuntes.SQL.Text := 'Select * From Apuntes Where coalesce(familia, '''') between ' + 
                             QuotedStr(DesdeFamilia.Text) + ' and  ' + QuotedStr(HastaFamilia.Text);
DMList.QApuntes.Open;

Saludos.

mightydragonlor 10-03-2012 23:12:37

Cita:

Empezado por guillotmarc (Mensaje 427338)
Hola.

Utiliza la función COALESCE de Firebird, con la que le indicas que si el campo es nulo, entonces considere otro valor (pasado como segundo parámetro).

Es decir :

Código Delphi [-]
DMList.QApuntes.Close;
DMList.QApuntes.SQL.Text := 'Select * From Apuntes Where coalesce(familia, '''') between ' + 
                             QuotedStr(DesdeFamilia.Text) + ' and  ' + QuotedStr(HastaFamilia.Text);
DMList.QApuntes.Open;

Saludos.

Claro que se puede, pero yo considero que no deba ser así, ya que usar este tipo de funciones hacen que las consultas sean mas lentas, llegando incluso a hacer table scan, así que el desempeño se ve claramente afectado, suelo usar el coalesce para la selección, pero lo trato de evitar al máximo en los where.

guillotmarc 11-03-2012 00:06:56

Hola.

Cita:

Empezado por mightydragonlor (Mensaje 427350)
Claro que se puede, pero yo considero que no deba ser así, ya que usar este tipo de funciones hacen que las consultas sean mas lentas, llegando incluso a hacer table scan, así que el desempeño se ve claramente afectado, suelo usar el coalesce para la selección, pero lo trato de evitar al máximo en los where.

Yo no tengo ninguna norma fija, depende del caso los uso sin problemas en los WHERE. Todo depende de la consulta, registros involucrados en el filtro, etc. ...

Pero sí, tienes razón en que algunas ocasiones (al igual que con cualquier otra consulta donde no añadas índices para su optimización) puede verse muy afectado el rendimiento. Y como siempre, la solución es simplemente añadir un índice para que el motor pueda optimizar adecuadamente esa consulta, en este caso sería un índice sobre una expresión :

CREATE INDEX APUNTES_FAMILIA ON APUNTES COMPUTED BY (COALESCE(FAMILIA, ''));


La franja horaria es GMT +2. Ahora son las 23:44:58.

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