Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Conexión con bases de datos
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Conexión con bases de datos

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 24-07-2003
fortran fortran is offline
Miembro
 
Registrado: may 2003
Ubicación: Asturias
Posts: 63
Poder: 22
fortran Va por buen camino
Filtrado de una tabla.

A ver si me podeis echar una mano porque en esto estoy más perdido que un pulpo en un garage.

Utilizo wxp y D5 y las tablas son Paradox.

Os cuento, tengo dos tablas en mi aplicación.
1.- TablaClientes.
2.- TablaVisitas.

En un formulario quiero que al seleccionar un cliente en un DBGrid me salgan las fechas de sus visitas (en otro dbgrid), hasta ahí bien, he hecho un maestro-detalle. Ahora lo que quiero es que al seleccionar una fecha de las que salen en el dbgrid me salgan los servicios realizados en esa fecha. Para ello puse un memo en el que volcaré los datos que encuentre para os servicios de esa fecha.

El volcado no me supone problema, el problemasurge porque quiero filtrar por fecha del siguiente modo:

Código PHP:
procedure TFormularioPrincipal.DBGridVisitasCellClick(ColumnTColumn);
begin
   modulodedatos
.tablavisitas.filter := 'FechaVisita = '
            
column.Field.AsString;
   
modulodedatos.tablavisitas.Filtered := TRUE;
   
rellenardatoscliente// es para cargar el memo
end
Bueno, pues cuando ejecuto el programo y hago click en una fecha me salta una excepción que dice:

EdatabaseError with message 'Arithmetic in filter expresions not supported'. ¿Como puedo solucionar esto?.
¿Sería mejor que buscase otra solución?.

Un saludo y gracias por vuestra atención.
__________________
- ¿Y cuando dejaré de aprender maestro?.

- El día que te mueras pequeño saltamontes.
Responder Con Cita
  #2  
Antiguo 24-07-2003
Avatar de Cabanyaler
Cabanyaler Cabanyaler is offline
Miembro
 
Registrado: jun 2003
Ubicación: País Valencià
Posts: 339
Poder: 21
Cabanyaler Va por buen camino
Bueno, en primer lugar yo te aconsejaria que trabajases o bien con consultas o vistas en lugar de con filtros, verás que mejoras el rendimiento y velocidad y disminuyes el tmp de respuesta del sistema.

Luego, creo que te falta mencionar que para los servicios tienes otra tabla ¿no?, la cual se encuentra relacionada en maestro:detalle con la tabla de visitas. Si no es así yo lo diseñaria de ese modo, ya que me parece mejor solución que no el volcarlo a un Memo. (es sólo mi opinión o consejo, vamos...)

En cuanto al error, muy probablemente salte por la naturaleza de los datos en los que estas intentando realizar el filtro, es decir, el
column.Field.AsString quizá es por el forzado de tipo String, mientras que el campo en el que estableces el filtro supongo que lo tendrás declarado como de tipo dateTime. Puede venir por ahí el error, creo yo.

Suerte.
__________________
El meu país és tan petit, que des de dalt d'un campanar es pot veure el campanar veí.
Responder Con Cita
  #3  
Antiguo 24-07-2003
__cadetill __cadetill is offline
Miembro
 
Registrado: may 2003
Posts: 3.387
Poder: 25
__cadetill Va por buen camino
Bueno, te habia respondido al otro hilo que tenias abierto y, luego me he dado cuenta que estaba este, asi que te pongo aqui lo que te habia contestado

Prueba algo asi

Código:
var
  str : string;
begin
  str := 'FechaVisita = ' + QuotedStr(FormatDateTime('mm/dd/yyyy', 
                     column.Field.AsDateTime));
  modulodedatos.tablavisitas.filter := str;
  modulodedatos.tablavisitas.filtered := true;
end;
Pero, si no he entendido mal, estas haciendo un master-detail1-detail2, no? Si es asi, puedes hacer que el detail1 sea el master del detail2 y presentar los datos en un TDbGrid, no se si me explico

Bueno, espero te sirva

PD: el formato de fecha dependera del motor de bases de datos que utilices (creo que en Paradox es eso, pero no recuerdo al 100%)

EDIT: para evitar el scroll horizontal

Última edición por __cadetill fecha: 25-07-2003 a las 15:53:30.
Responder Con Cita
  #4  
Antiguo 24-07-2003
fortran fortran is offline
Miembro
 
Registrado: may 2003
Ubicación: Asturias
Posts: 63
Poder: 22
fortran Va por buen camino
Hola a los dos:

Lo primero dar las gracias a Cadetil por cerrar el otro post (que era identico a este), creo que salió repetido porque le di al cabo del tiempo a refrescar la página.

He hecho lo que me dijo Cadetil y funciona, pero no me he quedado muy satisfecho, ya que al hacer el filtro también me desaparecen las otras fechas de visita.

La cuestión es que la tabla de visitas consiste en:

- 1 campo indice_visitas
- 1 campo clave_cliente
- 1 campo fecha_visita
- 7 campos servicio1, servicio2, servicio3, ...

(no es probable que en una visita se hagan más de 7 servicios).

En la tabla de servicios solamente he incluido:

- 1 Campo Clave_servicio
- 1 Campo Nombre_servicio
- 1 Campo Precio_servicio

Y luego tengo la tabla de clientes:

Con la clave_cliente, nombre_cliente...

Tal como lo tengo no puedo hacer un master:detail1:detail2.

¿Se os ocurre otra manera mejor de organizar las tablas?

Lo de hacer una consulta lo he intentado, pero me he liado ¿sabeis de algún sitio donde expliquen bien lo de las consultas?

Un saludo y gracias por vuestras respuestas.

PD: Cadetil, el formato de fecha en Paradox era (dd/mm/yy).
__________________
- ¿Y cuando dejaré de aprender maestro?.

- El día que te mueras pequeño saltamontes.
Responder Con Cita
  #5  
Antiguo 24-07-2003
Mick Mick is offline
Miembro
 
Registrado: may 2003
Posts: 405
Poder: 22
Mick Va por buen camino
Debes crear un indice secundario para el campo fecha_visita en la tabla de visitas, usa el database desktop para ello,
Una vez que tengas el indice definido , supongamos que le has llamado , ifecha_visita, primero tienes que activarlo para la tabla:

Tabla.IndexName:= 'ifecha_visita';

Lo que hara que los registros queden ordenador por el campo del indice (por fecha de visita).

Despues si solo quieres mostrar los registros de esa fecha harias algo como:

Tabla.SetRange( [ FechaInicial],[FechaFinal]);

para Cancelar el rango:

Tabla.CancelRange;

para Desactivar el indice

Table.IndexName:= '';

Pero parece que esta solucion no es la que te interesa, lo que quieres hacer es que se muestren todos los registros pero posicionarte en los de determinada fecha para ello haces algo como:

Tabla.FindNeares([FechaABuscar]);

La ventaja de usar indices, es que la operaciones sobre las tablas son infinitamente mas rapidas.

Salud2 !!
Responder Con Cita
  #6  
Antiguo 25-07-2003
__cadetill __cadetill is offline
Miembro
 
Registrado: may 2003
Posts: 3.387
Poder: 25
__cadetill Va por buen camino
Bien, tal y como lo veo, tenemos lo siguiente

Tabla Visitas --> Tabla Clientes con relacion N-->1

Esta relacion no hay problemas (segun comentas en tu primer post). Solo un comentario, el indice de la tabla visitas tendria que ser

ID_Cliente
ID_Visita

Siempre ha de ir el indice de la tabla maestra al principio y luego el indice de la detalle.

Ok, ya tenemos la relacion hecha.

Para la siguienta tebla, Servicios, esta no es un detalle de Visitas. Tal y como yo lo veo (por lo que pones), ésta es un maestro de Servidios que nos informa de qué servicio es y el precio.

Para hacer lo que quieres, es decir, coger la descripcion del servcio y el precio (creo entender que es eso), lo que yo haria es poner campos calculados en tu DataSet de Visitas que recuperaran la informacion que deseas de la tabla de Servicios

Es eso lo que quieres?

Ya nos contaras, espero te sirva
Responder Con Cita
  #7  
Antiguo 28-07-2003
fortran fortran is offline
Miembro
 
Registrado: may 2003
Ubicación: Asturias
Posts: 63
Poder: 22
fortran Va por buen camino
He hecho tal y como decía Cadetill:

TablaClientes --> TablaVisitas, y hasta ahí bien.

Para acceder al servicio que se ha hecho al tener el código he hecho lo siguiente:

Código:
Procedure RellenarDatosCliente;
Var
  i : integer;
  indicedeservicios:  array [1..7] of integer;
Begin
with FormularioPrincipal do
Begin
// recogida de indices de servicios
   indicedeservicios[1]:= modulodedatos.tablavisitasserviciorealizado1.value;
   indicedeservicios[2]:= modulodedatos.tablavisitasserviciorealizado2.value;
   indicedeservicios[3]:= modulodedatos.tablavisitasserviciorealizado3.value;
   indicedeservicios[4]:= modulodedatos.tablavisitasserviciorealizado4.value;
   indicedeservicios[5]:= modulodedatos.tablavisitasserviciorealizado5.value;
   indicedeservicios[6]:= modulodedatos.tablavisitasserviciorealizado6.value;
   indicedeservicios[7]:= modulodedatos.tablavisitasserviciorealizado7.value;
// Localización en la tabla de servicios de esos índices e inserción del nombre en
// el Memo1
   for i := 1 to 7 do
   Begin
   with modulodedatos.tablaserviciosclaveservicio do
   Begin
      modulodedatos.TablaServicios.First;
      While not eof do
         if value = indicedeservicios[i] then
            memo1.lines[i] := modulodedatos.TablaServiciosnombreservicio.Value
         else
            Next;
    End;
    End;
End;
End;
El problema es que me da un Class EInOutError con mensaje(I/O error 6). En la sentencia while not eof do. ¿por que?.
__________________
- ¿Y cuando dejaré de aprender maestro?.

- El día que te mueras pequeño saltamontes.
Responder Con Cita
  #8  
Antiguo 28-07-2003
__cadetill __cadetill is offline
Miembro
 
Registrado: may 2003
Posts: 3.387
Poder: 25
__cadetill Va por buen camino
Cita:
Posteado originalmente por fortran

While not eof do
sustituyelo por

Código:
modulodedatos.tablaserviciosclaveservicio.Eof
El with que haces, es sobre un TField, no sobre la tabla, de ahi el error ese, ya que tambien existe el EOF como funcion.

De todas maneras, desde mi punto de vista, el codigo que has puesto no es muy eficiente. Podrias mirar de sustituirlo por algo asi (que quizas no da tantas vueltas a la tabla)

Código:
var Q: TQuery;
begin
  Q := TQuery.Create(Self);
  Q.DatabaseName := modulodedatos.TablaServicios.DatabaseName;
  Q.SQL.Text := 'select nombreservicio from TablaServicios where claveservicio = :valor';
  try
    // primero
    Q.ParamByName('valor').Value := modulodedatos.tablavisitasserviciorealizado1.value;
    Q.Open;
    if not Q.Fields[0].IsNull then Memo1.Lines.Add(Q.Fields[0].AsString);
    // segundo
    Q.Close;
    Q.ParamByName('valor').Value := modulodedatos.tablavisitasserviciorealizado2.value;
    Q.Open;
    if not Q.Fields[0].IsNull then Memo1.Lines.Add(Q.Fields[0].AsString);
    // tercero
    Q.Close;
    Q.ParamByName('valor').Value := modulodedatos.tablavisitasserviciorealizado3.value;
    Q.Open;
    if not Q.Fields[0].IsNull then Memo1.Lines.Add(Q.Fields[0].AsString);
    // ........
  finally
    FreeAndNil(Q);
  end;
end;
Responder Con Cita
  #9  
Antiguo 28-07-2003
fortran fortran is offline
Miembro
 
Registrado: may 2003
Ubicación: Asturias
Posts: 63
Poder: 22
fortran Va por buen camino
Hola Cadetill.
He intentado las dos soluciones, vaya por delante que me parece más correcta la segunda. Pero ninguna la he podido llegar a concluir. En la primera me dice:
[Error] UtilidadesAplicacion.pas(28): Undeclared identifier: 'eof'

En el segundo caso (que es el que me gustaría implementar) no soy capaz de conseguir que me acepte el self:

Me sale
[Error] UtilidadesAplicacion.pas(52): Undeclared identifier: 'Self'.
__________________
- ¿Y cuando dejaré de aprender maestro?.

- El día que te mueras pequeño saltamontes.
Responder Con Cita
  #10  
Antiguo 28-07-2003
__cadetill __cadetill is offline
Miembro
 
Registrado: may 2003
Posts: 3.387
Poder: 25
__cadetill Va por buen camino
Veamos

Para la primera, mea culpa, hice un cortar y pegar y asi me feu

Tendria que haber sido

Código:
modulodedatos.tablaservicios.Eof
Osea, el EOF pertenece al DataSet, no al Field

La segunda opcion. No se donde estaras haciendo el Create (Form, DataModule,...), pero si no te acepta el Self, prueba Application (que esta definido en la unit Forms)

Espero te sirva
Responder Con Cita
  #11  
Antiguo 29-07-2003
fortran fortran is offline
Miembro
 
Registrado: may 2003
Ubicación: Asturias
Posts: 63
Poder: 22
fortran Va por buen camino
Hola Cadetill:

Lo primero decirte que la primera opción funcionó perfectamente, con la modificación que me dijiste y alguna más, para solucionar una metedura de pata que tenía en el código que hacía que no terminara nunca el bucle con while. Con la segunda me pongo ahora a ver si doy con la solución, de momento he de decirte que es un procedimiento que tengo en una unidad, en ningún formulario.

P.D.

El código de la primera opción (la mala) quedaría así:

Código:
Procedure RellenarDatosCliente;
Var
  i : integer;
  indicedeservicios:  array [1..7] of integer;
Begin
with FormularioPrincipal do
Begin
   for i := 1 to 7 do
   memo1.Lines[i]:= '';
   
// recogida de indices de servicios
   indicedeservicios[1]:= modulodedatos.tablavisitasserviciorealizado1.value;
   indicedeservicios[2]:= modulodedatos.tablavisitasserviciorealizado2.value;
   indicedeservicios[3]:= modulodedatos.tablavisitasserviciorealizado3.value;
   indicedeservicios[4]:= modulodedatos.tablavisitasserviciorealizado4.value;
   indicedeservicios[5]:= modulodedatos.tablavisitasserviciorealizado5.value;
   indicedeservicios[6]:= modulodedatos.tablavisitasserviciorealizado6.value;
   indicedeservicios[7]:= modulodedatos.tablavisitasserviciorealizado7.value;
// Localización en la tabla de servicios de esos índices e inserción del nombre en
// el Memo1
   for i := 1 to 7 do
   Begin
   with modulodedatos.tablaservicios do
   Begin
      modulodedatos.TablaServicios.First;
      While not eof do
         if modulodedatos.TablaServiciosClaveServicio.value = indicedeservicios[i] then
         Begin
            memo1.lines[i] := modulodedatos.TablaServiciosnombreservicio.Value;
            next;
         end
         else
            Next;
    End;
    End;
    For i := 1 to 7 do
    If memo1.Lines[i] = '0' then
       memo1.lines[i] := ''
End;
End;
__________________
- ¿Y cuando dejaré de aprender maestro?.

- El día que te mueras pequeño saltamontes.
Responder Con Cita
  #12  
Antiguo 29-07-2003
__cadetill __cadetill is offline
Miembro
 
Registrado: may 2003
Posts: 3.387
Poder: 25
__cadetill Va por buen camino
Cita:
Posteado originalmente por fortran
Con la segunda me pongo ahora a ver si doy con la solución, de momento he de decirte que es un procedimiento que tengo en una unidad, en ningún formulario.
Ok, por eso no te funciona el Self. Prueba lo que te comento de añadir Forms en el uses y utilizar Application


Cita:
Posteado originalmente por fortran
Código:
      While not eof do begin
         if modulodedatos.TablaServiciosClaveServicio.value = indicedeservicios[i] then
         Begin
            memo1.lines[i] := modulodedatos.TablaServiciosnombreservicio.Value;
            next;
         end
         else
            Next;
    End;
Respecto a este cacho de codigo, no crees que es lo mismo que hacer...
Código:
      While not eof do begin
         if modulodedatos.TablaServiciosClaveServicio.value = indicedeservicios[i] then
            memo1.lines[i] := modulodedatos.TablaServiciosnombreservicio.Value;
          Next;
    End;
y nos ahorramos alguna linea Ya que, sea cual sea el resultado de la condicion del IF vamos ha hacer un Next, podemos quitarlo de dentro del mismo
Responder Con Cita
  #13  
Antiguo 29-07-2003
fortran fortran is offline
Miembro
 
Registrado: may 2003
Ubicación: Asturias
Posts: 63
Poder: 22
fortran Va por buen camino
Tienes toda la razón nos ahorramos un par de líneas.

Con respecto a lo del application no he dado con ello. Probablemente porque no se la sintaxis que debo poner.
He probado varias cosas con distintos resultados (pero todos negativos) . He probado a poner

Q:= application.create(TQuery);

y me dice:
[Error] UtilidadesAplicacion.pas(56): Incompatible types: 'TComponent' and 'Class reference'

También he probado:

Q:= application.create(self);

y me dice:

[Error] UtilidadesAplicacion.pas(56): Undeclared identifier: 'self'
__________________
- ¿Y cuando dejaré de aprender maestro?.

- El día que te mueras pequeño saltamontes.
Responder Con Cita
  #14  
Antiguo 29-07-2003
__cadetill __cadetill is offline
Miembro
 
Registrado: may 2003
Posts: 3.387
Poder: 25
__cadetill Va por buen camino
cuando te decia que en lugar de Self utilizaras Application, me referia a algo asi

Q := TQuery.Create(Application);

A ver ahora que tal
Responder Con Cita
  #15  
Antiguo 01-08-2003
fortran fortran is offline
Miembro
 
Registrado: may 2003
Ubicación: Asturias
Posts: 63
Poder: 22
fortran Va por buen camino
Hola de nuevo Cadetill:

He tardado en responder porque he "pescado" un gripazo que me ha tenido en cama 2 días.

La solución que me propusiste funcionó a la perfección, solamente le añadí al principio del procedimiento una línea para borrar el memo1 antes de iniciar.

Por si a alguien le puede servir dejo aquí el código final.

Código:
Procedure RellenarDatosCliente;

var
Q: TQuery;
begin
with formularioprincipal do
Begin
  memo1.Lines.clear;
  Q := TQuery.create(Application);
  Q.DatabaseName := modulodedatos.TablaServicios.DatabaseName;
  Q.SQL.Text := 'select nombreservicio from TablaServicios where claveservicio = :valor';
  try
    // primero
    Q.ParamByName('valor').Value := modulodedatos.tablavisitasserviciorealizado1.value;
    Q.Open;
    if not Q.Fields[0].IsNull then Memo1.Lines.Add(Q.Fields[0].AsString);
    // segundo
    Q.Close;
    Q.ParamByName('valor').Value := modulodedatos.tablavisitasserviciorealizado2.value;
    Q.Open;
    if not Q.Fields[0].IsNull then Memo1.Lines.Add(Q.Fields[0].AsString);
    // tercero
    Q.Close;
    Q.ParamByName('valor').Value := modulodedatos.tablavisitasserviciorealizado3.value;
    Q.Open;
    if not Q.Fields[0].IsNull then Memo1.Lines.Add(Q.Fields[0].AsString);
    // ........
  finally
    FreeAndNil(Q);
  end;
End;
end;


Pues muchas gracias Cadetill, me has sido de gran ayuda.
__________________
- ¿Y cuando dejaré de aprender maestro?.

- El día que te mueras pequeño saltamontes.
Responder Con Cita
Respuesta



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 03:27:32.


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