Kompliziertes DBGrid Master-Detail
-
Hallo,
ich möchte 2 DBGrids in einer Master-Detail-Verknüpfung darstellen.
Die folgenden Tabellen stehen zur VerfügungTabelle1.................Tabelle2
Name.....ID_nr....... Artikel.......ID_nr
--------------------..... --------------------
Name1..1................Artikel1....1
Name1..3................Artikel2....2
Name1..5 ...............Artikel3....3
Name2..2................Artikel4....4
Name2..7 ...............Artikel5....5
Name3..34..............Artikel6....6
Name3..5 ...............Artikel7....7
Name3..2................Artikel8....8
usw.........................usw.Ziel ist die folgende Darstellung, wenn wie hier z.B. der 1.Eintrag (=Name1) im DBGrid1 angeklickt ist.
(Master) ..............(Detail)
DBGrid1................DBGrid2
.....Name...............Artikel....ID_nr
--------------------.....--------------------
-->Name1<---.......Artikel1.....1
....Name2..............Artikel3.....3
....Name3..............Artikel5.....5Läßt sich das Konstrukt mit dem Builder 6 umsetzen? Hat jemand eine Idee? Lassen sich auch SELECT..JOIN -Abfragen im Detailverknüpüfung durchführen?
DataSet bietet die Möglichkeit über DataSet->MasterFields Verknüpfungen herzustellen.
Aber damit bekomme ich nur 1-n-Verknüpfungen, was hier aber nicht ausreichtDataSetDetail->DataSource = DataSourceMaster; DataSetDetail->MasterFields = "ID_nr"; DBGridMaster->DataSource = DataSourceMaster; DataSourceMaster->DataSet = DataSetDetail;
-
thunderbol4 schrieb:
Läßt sich das Konstrukt mit dem Builder 6 umsetzen? Hat jemand eine Idee? Lassen sich auch SELECT..JOIN -Abfragen im Detailverknüpüfung durchführen?
Du könntest eine View in der DB definieren, die dann als Detail verwendet wird. Muß dieses DBGrid aktualisierbar sein? Welches RDBMS?
-
Hallo @witte,
witte schrieb:
Muß dieses DBGrid aktualisierbar sein? Welches RDBMS?
Nein, in den beiden DGrids wird nichts editiert. Die Einträge können nur angeklickt werden und dienen später zur Auswahl.
TDBGridOptions dbgO << dgRowSelect << dgMultiSelect;
Ich weiß nicht, was Du mit RDBMS meinst. Wenn Du die DB meinst, mit der ich arbeite: MySQL 5.
Was meinst Du mit View erstellen?
-
Du sagst, dass die Beziehung n:m ist.
Du könntest nun eine View definieren, welche Artikel und die Name-Artikel-Verknüpfungstabelle verjoint und den Fremdschlüssel zu Name in dieser Name-Artikel-Verknüpfungstabelle könntest Du dann in Beziehung zu der Mastertabelle setzen.
http://dev.mysql.com/doc/refman/5.0/en/create-view.html
-
Danke @witte,
das mit dem VIEW kannte ich noch nicht.
Ich muß mich hier erst noch einlesen.
Wenn ich Dich richtig verstehe, ist die von mir gewünschte Master-Detail-Ansicht mit dem BCB möglich.
Über den Fremdschlüssel aus der Abfrage/JOIN werden Master u Detail verbunden.Ich versuch das 'mal umzusetzen. Ich melde mich noch 'mal.
Vielen Dank.
-
Hallo,
wie angekündigt eine abschließende Meldung.
Ich habe den Tip von @witte umgesetzt, alles klappt super.
Hier die grobe Vorgehensweise für evtl MySQL-Interessierte an dem hier zurückliegend dargestelltem Beispiel Name, Artikel.AnsiString SQLBefehl; //Befehlssequenz zur Erstellung der VIEW AnsiString Sql1; //Befehlsequenz zur Erstellung des DataSets für Master AnsiString Sql2; //Befehlsequenz zur Erstellung des DataSets für Detail aus VIEW SQLBefehl = "DROP VIEW IF EXISTS myview;"; //evtl. bereits erstellte VIEW löschen ADOCommandExec(SQLBefehl); SQLBefehl = "CREATE VIEW myview AS SELECT n.Name, n.ID_nr, a.Artikel FROM Tabelle1 n JOIN Tabelle2 a ON n.ID_nr = a.ID_nr ORDER BY n.Name;"; ADOCommandExec(SQLBefehl); Sql1 = "SELECT DISTINCT n.* FROM Tabelle1 n ORDER BY n.Name;"; Sql2 = "SELECT m.Artikel, m.ID_nr FROM myview m;"; ------------------------------------------ PrepGrids(Sql1, Sql2, "ID_nr"); //Funktion, die die Abfragen aus Sql1 und Sql2 für die DataSets des Haupt- u Detail-DBGrids durchführt und die DataSets belegt, //und desweiteren dem DetailDataSet->MasterFields = "ID_nr" das gemeinsame Feld zuweist. ------------------------------------------ void TForm1::ADOCommandExec(AnsiString SQLBefehl) { TADOCommand *tadc; tadc = new TADOCommand(NULL); tadc->Connection = ADOConnection1; //Verbindung zu MySQL tadc->CommandType = cmdText; tadc->CommandText = SQLBefehl; tadc->Execute(); delete tadc; tadc = NULL; }
-
Danke für die abschließende Rückmeldung.
Hast Du das auch mal ohne View ausprobiert, also den Select aus der View direkt im Select des Detail-Datasets zu verwenden? Sollte meiner Meinung nach auch funktionieren.
-
Joe_M. schrieb:
Hast Du das auch mal ohne View ausprobiert, also den Select aus der View direkt im Select des Detail-Datasets zu verwenden? Sollte meiner Meinung nach auch funktionieren.
Ich verwende das mit den DBExpress-Typen (PostgreSQL, BCB 6, TSQLClientDataSet und Konsorten) und habe damals die Arbeitsweise dieser Master/Details mit einem Netzwerksniffer überprüft. Dabei wurde nach einem Scrollen des Mastercursors in eine neue, noch nicht besuchte Zeile automatisch ein SQL-Stmt abgesetzt um die Detailinformationen zu holen. Diese wurden dann in das Detail angefügt.
Das System arbeitet so, dass es an das Detail-SQL ein "WHERE <keyspalte>=<primkeywert>" drangehangen und und an die DB angefragt wird. Bei seinem Beispiel würde das zu einer Syntax-Fehlermeldung führen, da nach ORDER BY kein WHERE mehr erfolgen darf.
-
Hm, ich hab keine Zeit das zu testen, aber das sollte dennoch funktionieren, sonst dürftest Du ja überhaupt keine Bedingungen im Detail-Select haben, da dies immer zu einem Syntaxfehler führen würde?
-
Das war das Problem, was ich damals erlebt habe. Hinzu kam noch, dass beim Abfragen der Detailinfos der Primärschlüsselname in der Where-Bedingung auftauchte, nicht der Fremdschlüsselname. Wir verwenden den DBExpress-PostgreSQL-Treiber von VitaVoom, möglicherweise ist auch dort der Hund begraben. Ich habe mich damals mit einer View beholfen um weiter zu kommen, wenn das Problem sonstwo nicht auftaucht, umso besser.