Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Master-Detail-Beziehung zur Laufzeit erstellen (https://www.delphipraxis.net/23013-master-detail-beziehung-zur-laufzeit-erstellen.html)

barnti 27. Mai 2004 15:09


Master-Detail-Beziehung zur Laufzeit erstellen
 
Hallo,
ich versuche zur Laufzeit eineMaster-Detail Beziehung zwischen zwei Tabellen zu erzeugen.
Delphi-Quellcode:
DetailQuery.Close;
DetailQuery.Datasource:= MasterDatasource;
DetailQuery.SQL.Clear;
DetailQuery.SQL.Add('SELECT *');
DetailQuery.SQL.Add('FROM '+TableName);  // Abzufragende Tabelle
DetailQuery.SQL.Add('WHERE '+KeyField+'='+':'+KeyField); // Fremdschlüssel als QueryParameter
DetailQuery.Open;
Leider bekomme ich beim Zugriff (ScrollEvent) des Detail-Datasets immer eine AV.


Weiß jemand Rat?

Stevie 27. Mai 2004 15:13

Re: Master-Detail-Beziehung zur Laufzeit erstellen
 
Ist die MasterSource auch offen?

barnti 27. Mai 2004 15:13

Re: Master-Detail-Beziehung zur Laufzeit erstellen
 
Zitat:

Zitat von Stevie
Ist die MasterSource auch offen?

Japp.

barnti 27. Mai 2004 15:38

Re: Master-Detail-Beziehung zur Laufzeit erstellen
 
Hallo,

Korrektur: Die Fehlermeldung lautet: "DetailQuery: Field '' not found "

Kann jemand damit etwas anfangen? Ich schätze, dass der Parameter nicht erkannt wird?!

Stevie 27. Mai 2004 15:46

Re: Master-Detail-Beziehung zur Laufzeit erstellen
 
Stichwort: MasterField
Du musst dem DataSet sagen, über welches Feld es mit dem Master verbunden ist.

barnti 27. Mai 2004 18:01

Re: Master-Detail-Beziehung zur Laufzeit erstellen
 
Hallo Steve,

wie Du am Statement erkennen kannst, verwende ich einen Parameter. Dieser stellt die Verbindung her...

Aber vielleicht ist das so nicht ganz richtig oder wird nicht richtig erkannt?

barnti 28. Mai 2004 08:34

Re: Master-Detail-Beziehung zur Laufzeit erstellen
 
Hallo,

meine Query enthält das richtige Statement mit dem Parameter, wenn ich es mir anzeigen lasse.
Trotzdem funktioniert es nicht. Ich bekomme immer ein leeres DetailDataset.

Wenn ich folgendes mache:
Delphi-Quellcode:
Query.Close;
Query.SQL.Clear;
Query.SQL.Add('SELECT *');
Query.SQL.Add('FROM '+TableName);
Query.SQL.Add('WHERE '+KeyName+'='+QuotedStr(2)) // Hier gebe ich den Fremdschlüssel direkt an,
                                                 // statt über Parameter.
...
So geht es. Ich verstehe das nicht.

Ich habe zwei Querys:

1. Kunde
Kunde_ID

2. Waren
Waren_ID
Kunde_ID

Ich möchte die folgende Master-Detail-Beziehung zur Laufzeit, beim erzeuge der Querys, erstellen.
Delphi-Quellcode:
WarenQuery.Close;
WarenQuery.SQL.Clear;
WarenQuery.SQL.Add('SELECT *');
WarenQuery.SQL.Add('FROM '+TableName);
WarenQuery.SQL.Add('WHERE '+KeyName+'=:'+KeyName) // Wobei 'KeyName' der Parameter dieser Query
                                                  // ist
Lasse ich mir das Statement beim Scrollen ausgeben, so steht der Parameter mit in der Query.
Nur das Ergebnis bleibt leer, obwohl ein Wert vorhanden sein sollte...

Kann jemand helfen und mir sagen wie ich den Parameter richtig miteingebunden bekomme?

Sharky 28. Mai 2004 08:47

Re: Master-Detail-Beziehung zur Laufzeit erstellen
 
Hai barnti,

an welcher Stelle setzt Du denn den Wert des Parameters?

barnti 28. Mai 2004 09:13

Re: Master-Detail-Beziehung zur Laufzeit erstellen
 
Hallo Sharky,
Zitat:

Zitat von Sharky
an welcher Stelle setzt Du denn den Wert des Parameters?

Ich erzeuge DBLookupBoxen sobald man eine Tabelle zur Ansicht aufruft. Die LookupBoxen dienen der Suche in der Tabelle. So kann man in der Tabelle 'Waren' nach Waren von bestimmten Kunden suchen, wenn man in der LookupBox 'Kunde' einen Kunden auswählt. In der nächsten Lookupbox sollen dann nur noch Waren des ausgewählten Kunde angezeigt werden.
Die Boxen werden erzeugt sobald der Benutzer auf den 'Tabelle Waren anzeigen'-Button drückt.
Delphi-Quellcode:
...
procedure SetExtraLookup(...)
...// Hier wird jeweils eine Box mit einem Standard-SQL-Statement konfiguriert(alle Daten der  
   // Tabelle)
ListField:= GetListFieldLookupBox.ListSource:= GetXLookupDatasource(Tablename);
LookupBox.ListSource.DataSet.Open;
LookupBox.KeyField:= LookupBox.ListSource.DataSet.Fields[0].FieldName;
LookupBox.ListField:= ListField;

SetMasterDetail(LookupBox);  // hier soll die Master-Detail-Beziehung etabliert werden
...


procedure SetMasterDetail(LookupBox: TDBLookupComboBox);
begin
...
  // Neu abzufragende Tabelle, Fremdschlüssel und die zugehörige Query
  Tablename:= GetTableName;
  KeyName:= MasterDataset.Fields[0].FieldName;
  DetailQuery:= GetDetailQuery;

  DetailQuery.Datasource:= MasterDatasource // Hier wird die Verbindung beider Quellen hergestellt

  DetailQuery.Close;           // Hier wird das Statement neu gesetzt, so dass der
                                // Parameter 'KeyName'
  DetailQuery.SQL.Clear;            // ermittelt aus dem Masterdataset eingesetzt wird
  DetailQuery.SQL.Add('SELECT *');
  DetailQuery.SQL.Add('FROM '+TableName);
  DetailQuery.SQL.Add('WHERE '+KeyName+'=:'+KeyName)};
  DetailQuery.SQL.Add('and valid is Null');
  DetailQuery.Open;
end;
Der Wert des Parameters ergibt sich aus der Verbindung der beiden Quellen. Da In der LookupBox 'Kunde' Werte vorhanden sind, scheint die Quelle 'Kunde' offen zu sein. In der Box der Waren werden halt nur keine Waren angezeigt. Das Statement wird aber ausgeführt...

Stevie 28. Mai 2004 10:50

Re: Master-Detail-Beziehung zur Laufzeit erstellen
 
Zitat:

Zitat von barnti
Hallo Steve,

wie Du am Statement erkennen kannst, verwende ich einen Parameter. Dieser stellt die Verbindung her...

Aber vielleicht ist das so nicht ganz richtig oder wird nicht richtig erkannt?

Hmm, so hab ich das noch nie gemacht, heißt aber nix.
Du musst aber nicht die Where-Klausel in die Abfrage miteinfügen, sondern über Masterfield die Beziehung festlegen.
Dann wird auch die Detail-Datenmenge aktualisiert, wenn sich die Master-Datenmenge ändert.

barnti 28. Mai 2004 11:05

Re: Master-Detail-Beziehung zur Laufzeit erstellen
 
Hi,

das geht auch über die Parameter der Where-Klausel. Habe ich vorher bereits gemacht.

MarkusB 30. Mai 2004 13:33

Re: Master-Detail-Beziehung zur Laufzeit erstellen
 
Hallo branti!
Ich habe versucht Dein Problem nachzubilden. Ich habe 2 TQuery, 2 TDataSource, 2 TDBLookupListBox und ein TButton auf der Form platziert ohne irgendeine Eigenschaft der Elemente im Objektinspektor gesetzt zu haben. Alle Eigenschaften sollten während der Laufzeit gesetzt bzw. manipuliert werden. Dadurch ist der folgende Code entstanden und der funktioniert prima.

Und hier der vollständige Code:
Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  Db, DBTables, StdCtrls, DBCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;

    MasterQuery: TQuery;
    MasterDataSource: TDataSource;
    MasterDBLookupListBox: TDBLookupListBox;

    DetailQuery: TQuery;
    DetailDataSource: TDataSource;
    DetailDBLookupListBox: TDBLookupListBox;

    procedure Button1Click(Sender: TObject);
    procedure MasterDBLookupListBoxClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
begin
  // MasterQuery
  MasterQuery.Active := false;
  MasterQuery.DatabaseName := 'FAM001_Lvs';

  MasterQuery.SQL.Clear;
  MasterQuery.SQL.Add('select distinct dnote_id from disp_head');

  MasterQuery.Prepare;

  MasterQuery.Active := true;

  // MasterDataSource
  MasterDataSource.DataSet := MasterQuery;

  // MasterDBLookupListBox
  MasterDBLookupListBox.ListSource := MasterDataSource;
  MasterDBLookupListBox.KeyField := 'dnote_id';

  // DetailQuery
  DetailQuery.Active := false;
  DetailQuery.DatabaseName := 'FAM001_Lvs';

  DetailQuery.SQL.Clear;
  DetailQuery.SQL.Add('select distinct art_id from disp_line');
  DetailQuery.SQL.Add(' where dnote_id = :dnote_id');

  DetailQuery.ParamByName('dnote_id').AsInteger;
  DetailQuery.Prepare;

  DetailQuery.DataSource := MasterDataSource;
  DetailQuery.Active := true;

  // DetailDataSource
  DetailDataSource.DataSet := DetailQuery;

  // DetailDBLookupListBox
  DetailDBLookupListBox.ListSource := DetailDataSource;
  DetailDBLookupListBox.KeyField := 'art_id';
end;

procedure TForm1.MasterDBLookupListBoxClick(Sender: TObject);
begin
  // DetailQuery neuaufbauen
  DetailQuery.Active := false;
  DetailQuery.Active := true;
end;

end.
Ich hoffe, dass ich Dir helfen konnte.

Viele Grüße
Markus
:gruebel:

barnti 1. Jun 2004 07:18

Re: Master-Detail-Beziehung zur Laufzeit erstellen
 
Hallo MarkusB,

das entspricht in etwa dem, was ich auch implementiert habe. Wie gesagt bei mir funktioniert es nicht. Das Problem dabei ist, dass ich beim 'OnScroll-Ereignis' die Datasets und ihre Abhängigkeiten aktualisieren muss. Dabei scheint das Problem aufzutauchen. Vielleicht finde ich den Fehler noch.
Danke für die Mühe! Sollte ich das Problem gelöst haben, werde ich es hier berichten...

barnti 1. Jun 2004 10:30

Re: Master-Detail-Beziehung zur Laufzeit erstellen
 
Hallo,

jetzt habe ich das Problem gelöst. Es funktioniert mit der normalen Master-Detail-Verbindung.
Folgende Komponenten konfiguriert:

Delphi-Quellcode:
...
MasterLookupBox.ListSource:= MasterSource;
DetailLookupBox.ListSource:= DetailSource;

MasterLookupBox.ListField:= 'ListFieldName'
DetailLookupBox.ListField:= 'ListFieldName';

MasterLookupBox.KeyField:= 'KeyName';
DetailLookupBox.KeyField:= 'KeyName';

...


procedure LookupBoxOnEnter(Sender: TObject);
begin
  SetMasterDetail(TDBLookupComboBox(Sender));
end;

procedure SetMasterDetail(...)
begin
  ...
  // Query der LookupBox
  DetailQuery.DataSource:= MasterLookupBox.ListSource;

  Tablename:= GetTableName;
  KeyName:= MasterLookupBox.ListSource.KeyName;
  DetailQuery:= GetQuery(TableName);

  // Parameter einfügen
  DetailQuery.Close;
  DetailQuery.SQL.Clear;
  DetailQuery.SQL.Add('SELECT * ');
  DetailQuery.SQL.Add('FROM '+Tablename);
  DetailQuery.SQL.Add('WHERE '+KeyName+'=:'+KeyName);
  DetailQuery.Open;
end;
Das in Kurzform. Für weitere Fragen stehe ich gern zur Verfügung.

Woran es jetzt gelegen hat vermag ich nicht zu sagen. Wahrscheinlich lag es am Zeitpunkt des Setzens der Master-Detail-Beziehung. So geht es auf jeden Fall.

Nochmals Danke an alle.


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:56 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz