Kompliziertes DBGrid Master-Detail



  • Hallo,
    ich möchte 2 DBGrids in einer Master-Detail-Verknüpfung darstellen.
    Die folgenden Tabellen stehen zur Verfügung

    Tabelle1.................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.....5

    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?

    DataSet bietet die Möglichkeit über DataSet->MasterFields Verknüpfungen herzustellen.
    Aber damit bekomme ich nur 1-n-Verknüpfungen, was hier aber nicht ausreicht

    DataSetDetail->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.


Anmelden zum Antworten