Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Conexión con bases de datos (https://www.clubdelphi.com/foros/forumdisplay.php?f=2)
-   -   problema con tablas Maestro-Detalle (https://www.clubdelphi.com/foros/showthread.php?t=88660)

DANIEL1818 11-07-2015 22:23:49

problema con tablas Maestro-Detalle
 
Hola! voy directo al grano, tengo dos tablas (en ACCESS): una de PRODUCTOS y otra de COMENTARIOS que la gente puede hacerle a esos productos (con relación maestro-detalle). Tengo un ADOTable asociado a la tabla COMENTARIOS.

En mi formulario tengo un DBGrid asociado a un ADOQuery que me muestra el titulo de los productos, y cuando voy bajando o subiendo en el DBGrid me va mostrando los comentario para dichos productos en otro dbgrid llamado "DBgrid_Comentarios".

EL PROBLEMA: la tabla comentarios tiene un campo booleano "estado_comentario" que me dice si esta borrado o no. Lo que quiero poder hacer es que cuando esta BORRADO no me lo muestre en la tabla de detalles (osea en el DBGrid_comentarios)

¿Cómo podría solucionar este inconveniente?

Ya que en el ADOTable de la tabla COMENTARIOS en la propiedad "Filter" no me deja usarla porque me sale un cartel que "esta propiedad no está disponible para tablas detalles"

Espero que me puedan ayudar!! espero sus respuestas, desde ya muchísimas gracias por adelantado!

ecfisa 11-07-2015 23:33:21

Hola DANIEL1818.

Reemplaza el componente ADOTable (detalle) por un ADOQuery y luego este código:
Código Delphi [-]
procedure TForm.FormCreate(Sender: TObject);
begin
  qyDetail.Close;
  qyDetail.DataSource := dsMaster; // DataSource -> Tabla maestro
  qyDetail.SQL.Clear;
  qyDetail.SQL.Add('SELECT * FROM TABLA_DETALLE');
  qyDetail.SQL.Add('WHERE MASTER_ID = :ID AND ESTADO_COMENTARIO <> :BORRADO');
  qyDetail.Parameters.ParamByName('BORRADO').Value := 'DATO_BORRADO';
  qyDetail.Open;
end;
También deberás cambiar:
  • TABLA_DETALLE por el nombre que le hayas dado a la tabla detalle.
  • MASTER_ID por el nombre de la columna de la tabla detalle que referencia a la columna clave de la tabla maestro.
  • ID por el nombre de la columna clave de la tabla maestro. (No quites los dos puntos ":" que preceden al nombre o no funcionará)
  • DATO_BORRADO por el tipo y valor que posee la columna ESTADO_COMENTARIO.
saludos :)

DANIEL1818 12-07-2015 01:29:04

Cita:

Empezado por ecfisa (Mensaje 494308)
Hola DANIEL1818.

Reemplaza el componente ADOTable (detalle) por un ADOQuery y luego este código:
Código Delphi [-]
procedure TForm.FormCreate(Sender: TObject);
begin
  qyDetail.Close;
  qyDetail.DataSource := dsMaster; // DataSource -> Tabla maestro
  qyDetail.SQL.Clear;
  qyDetail.SQL.Add('SELECT * FROM TABLA_DETALLE');
  qyDetail.SQL.Add('WHERE MASTER_ID = :ID AND ESTADO_COMENTARIO <> :BORRADO');
  qyDetail.Parameters.ParamByName('BORRADO').Value := 'DATO_BORRADO';
  qyDetail.Open;
end;
También deberás cambiar:
  • TABLA_DETALLE por el nombre que le hayas dado a la tabla detalle.
  • MASTER_ID por el nombre de la columna de la tabla detalle que referencia a la columna clave de la tabla maestro.
  • ID por el nombre de la columna clave de la tabla maestro. (No quites los dos puntos ":" que preceden al nombre o no funcionará)
  • DATO_BORRADO por el tipo y valor que posee la columna ESTADO_COMENTARIO.
saludos :)








Gracias por tu respuesta, unas preguntas: 1) el codigo lo pongo en el evento onCreate del formulario que tiene las dos grillas no(la que me muestra el producto y el detalle)?
2)la verdad no entendi muy bien, ya que nunca lo hice de esta forma y estoy un poco perdido,ya puse ese codigo como me dijiste y ya en la primer linea me tira error fuera de memoria, lo que hice fue agregar un ADOQuery en el datamodule, y no lo active ni nada porque no me deja ya que no tiene escrito en su interior sentencia sql. El codigo que puse en el evento onCreate fue:
Código Delphi [-]
  procedure TForm1.FormCreate(Sender: TObject);
begin
  DM.QueryDETALLEComentario.Close;
  DM.QueryDETALLEComentario.DataSource := DM.ds_productos; // DataSource -> Tabla maestro
  DM.QueryDETALLEComentario.SQL.Clear;
  DM.QueryDETALLEComentario.SQL.Add('SELECT * FROM Comentario');
  DM.QueryDETALLEComentario.SQL.Add('WHERE id_sub = :id_sub AND estado_comentario <> :BORRADO');
  DM.QueryDETALLEComentario.Parameters.ParamByName('BORRADO').Value := true;
  DM.QueryDETALLEComentario.Open;
end;


No entiendo como puedo hacer para que funcione, porque que pasa con el dbgrid_Comentario (DETALLE) en el formulario? lo asocio al query que me dijiste que ponga en reemplazo del ADOtable que tenia antes? porque ya lo hice y tampoco funciona. El dbgrid que me muestra todos los productos esta asociado a varias querys, ya que se puede filtrar por fecha, por nombre del producto etc.

Espero tu respuesta! y muchas gracias por tu ayuda!

ecfisa 12-07-2015 02:39:06

Hola.

1) Si como parece en tu código tenes los DataSources en el DataModule (DM), podes hacer todas las asignaciones al ADOQuery en tiempo de diseño, inclusive la propiedad SQL y sólo tendrías que abrir y cerrar el query en el form que desees mostrar los datos.

2) En este caso el ADOQuery reemplaza al ADOTable, de modo que tendrá que tener un DataSource asociado y en la propiedad DataSource del DBGrid (detalle) deberá figurar el nuevo DataSource.

Yo hice toda la asignación por código para que se viera mas claramente las asignaciones, pero no es estríctamente necesario.

Es decir, si lo tenes armado de este modo,

en la propiedad DataSource del DBGrid del detalle tendría que figurar DM.dsDetail.

Saludos :)

DANIEL1818 12-07-2015 18:59:53

Cita:

Empezado por ecfisa (Mensaje 494316)
Hola.

1) Si como parece en tu código tenes los DataSources en el DataModule (DM), podes hacer todas las asignaciones al ADOQuery en tiempo de diseño, inclusive la propiedad SQL y sólo tendrías que abrir y cerrar el query en el form que desees mostrar los datos.

2) En este caso el ADOQuery reemplaza al ADOTable, de modo que tendrá que tener un DataSource asociado y en la propiedad DataSource del DBGrid (detalle) deberá figurar el nuevo DataSource.

Yo hice toda la asignación por código para que se viera mas claramente las asignaciones, pero no es estríctamente necesario.

Es decir, si lo tenes armado de este modo,

en la propiedad DataSource del DBGrid del detalle tendría que figurar DM.dsDetail.

Saludos :)



Hola nuevamente, no pude lograrlo, lo hice de esta forma porque ya no se como hacerlo a ver si me podes dar una mano:
Este código lo hice en el evento form Activate del que tiene la grilla maestro y detalle:

Código Delphi [-]
     DM.QueryDETALLEComentario.DataSource:= DM.ds_QueryTodosLosProductos;
     DM.QueryDETALLEComentario.Close;
     DM.QueryDETALLEComentario.Open;

y esta sentencia SQL lo puse en el queyDetalles (el que tuve que reemplazar por el ADOTable_detalle):

Código SQL [-]
SELECT C.*
 FROM Comentario C, Subasta_prod S
 WHERE (C.id_sub = S.id_sub) AND (C.estado_comentario <> true)

Los dos puntos que me dijiste que se los deje, se los tuve que sacar porque sino no me mostraba nada en la grilla detalle,(porque ademas si se anteponen los " : " seria un parametro, y no se que parametro se le pasaría ya que al ir bajando en la Grilla maestro me tiene que mostrar los comentarios de dicho producto, osea si tengo una mesa que me muestre los comentarios de la mesa, bajo un registro en la grilla y tengo una bicicleta entonces solo quiero que me muestre los comentarios de la bicicleta y esto no pasa.)

Está bien de la forma que estoy escribiendo el codigo en Delphi y el SQL en el querydetalle? o que mas me hace falta?

La conexión que hice fue: a la grillaMaestro le asigne el dataSource-->> DM.ds_QueryTodosLosProductos; //esta consulta me muestra todos los productos, y no lo conecto directamente a la tabla maestro ya que voy a tener que hacer distintos tipos de filtrado por titulo de producto, por fecha de publicacion de producto etc, entonces al DataSet del DataSource ds_QueryTodosLosProductos le voy a ir seteando los distintos querys que me realizan los distintos filtrados.

Espero tu respuesta y desde ya muchísimas gracias por tus gratas ayudas!

ecfisa 12-07-2015 23:18:08

1 Archivos Adjunto(s)
Cita:

Empezado por DANIEL1818 (Mensaje 494320)
Los dos puntos que me dijiste que se los deje, se los tuve que sacar porque sino no me mostraba nada en la grilla detalle,(porque ademas si se anteponen los " : " seria un parametro, y no se que parametro se le pasaría ya que al ir bajando en la Grilla maestro me tiene que mostrar los comentarios de dicho producto...

Si los quitas no funciona. Si, es un parámetro implícito y es precísamente el encargado de establecer la relación Master-Detail. Es la columna clave de la tabla maestro indicada mediante la propiedad DataSource.

Creo que lo mejor es que te adjunte un ejemplo simple y funcionando de lo que te estoy diciendo. Para el mismo uso las tablas customer y orders de dbdemos.mdb (viene con Delphi).

El ejemplo filtra quitando los distintos "PaymentMethods" desde un ComboBox y quita el filtrado desde un Button. Crea una carpeta y descomprime el demo allí.

Saludos :)

DANIEL1818 13-07-2015 00:24:13

Cita:

Empezado por ecfisa (Mensaje 494321)
Si los quitas no funciona. Si, es un parámetro implícito y es precísamente el encargado de establecer la relación Master-Detail. Es la columna clave de la tabla maestro indicada mediante la propiedad DataSource.

Creo que lo mejor es que te adjunte un ejemplo simple y funcionando de lo que te estoy diciendo. Para el mismo uso las tablas customer y orders de dbdemos.mdb (viene con Delphi).

El ejemplo filtra quitando los distintos "PaymentMethods" desde un ComboBox y quita el filtrado desde un Button. Crea una carpeta y descomprime el demo allí.

Saludos :)



Lo probe y no funciona, el codigo que puse en el evento onCreate del formulario es este(probe moviendo para arriba y para abajo las distintas lineas de codigo, como por ejemplo activando el query arriba de todo, en el medio como ahora y no funciona):


Código Delphi [-]
  DM.QueryDETALLEComentario.Close;
  DM.QueryDETALLEComentario.SQL.Clear;
  DM.QueryDETALLEComentario.SQL.Add('SELECT * FROM Comentario');
  DM.QueryDETALLEComentario.SQL.Add('WHERE id_sub = :id_sub AND estado_comentario <> :BORRADO');
  DM.QueryDETALLEComentario.Active:=true;
  DM.QueryDETALLEComentario.DataSource := DM.ds_queryCategorias; // DataSource -> Tabla maestro
  DM.QueryDETALLEComentario.Parameters.ParamByName('BORRADO').Value := true;
  DM.QueryDETALLEComentario.Open;


Siempre tira el error "Access violation at address 05AC644 in module 'Project1.exe'. Read of address 000003E0"


y en un momento cuando puse el DM.QueryDETALLEComentario.DataSource := DM.ds_queryCategorias; arriba de todo me decia que no se podia porque era como que se linkeaba de manera circular

Casimiro Notevi 13-07-2015 00:26:17

¿Por qué cambias el código?, lo puesto por ecfisa es:

Código Delphi [-]
    qyDetail.Close; 
    qyDetail.SQL.Clear; 
    qyDetail.SQL.Add('SELECT * FROM ORDERS'); 
    qyDetail.SQL.Add('WHERE CUSTNO = :CUSTNO AND PAYMENTMETHOD <> :BORRADO'); 
    qyDetail.Parameters.ParamByName('BORRADO').Value := cb.Items[cb.ItemIndex]; 
    qyDetail.Open;

ecfisa 13-07-2015 01:03:02

Cita:

Empezado por DANIEL1818 (Mensaje 494322)
Lo probe y no funciona...

Esa afirmación es incorrecta, el ejemplo que te adjunté funciona tál como se puede ver en esta imágen:



Pero como bien te indica Casimiro, si cambias el código...

Saludos :)

nlsgarcia 13-07-2015 01:50:28

DANIEL1818,

Cita:

Empezado por DANIEL1818
...Lo probé y no funciona...

:rolleyes:

Te comento:

1- El ejemplo suministrado en el Msg #6 (Relación Master-Detail) funciona correctamente según lo esperado ^\||/

2- Te sugiero revisar el mencionado ejemplo detalladamente para comprender su funcionamiento, no realices ningún cambio al código hasta que asimiles la mecánica del mismo.

Revisa esta información:
Espero sea útil :)

Nelson.

DANIEL1818 13-07-2015 23:46:15

Muchas gracias por sus respuestas!! ya lo probe bien! :)


La franja horaria es GMT +2. Ahora son las 13:22:05.

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