AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken Delphi MSSQL - Problem mit Rekursiver SP
Thema durchsuchen
Ansicht
Themen-Optionen

MSSQL - Problem mit Rekursiver SP

Offene Frage von "siles"
Ein Thema von siles · begonnen am 28. Jan 2008 · letzter Beitrag vom 28. Jan 2008
Antwort Antwort
siles

Registriert seit: 14. Jan 2008
34 Beiträge
 
#1

MSSQL - Problem mit Rekursiver SP

  Alt 28. Jan 2008, 16:02
Datenbank: MSSQL • Version: 2000 • Zugriff über: ADO
Moin
Ich habe ein kleines Problem mit einer Rekursion und zwar muss ich eine TreeView aus einer Datenbank erstellen, mit ID, ParentID etc. Ihr kennt das bestimmt.

Um die Nodes in geordneter Reihenfolge aus der Datenbank zu bekommen, habe ich die Stored Procedure von Omata (http://www.delphipraxis.net/internal...ht=stored+baum) benutzt.

Im Grunde funktioniert das ganz gut, nur bei tiefen Bäumen (Vlt. so ab 12, weiss es nicht mehr genau) bekomme ich nur noch 2 leere Nodes und dann ist schluss.

Wenn ich die Stored Procedure allerdings im Query Analyzer aufrufe, zeigt es mir alle Nodes mit ihren IDs und Parent IDS sowie dem Level an.


Verstehen tu ich es nicht, aber da alzaimar geschrieben hat, dass diese Lösung bei tiefen Bäumen versagt, glaube ich das einfach mal.

Die Frage ist, wie ich das nun lösen soll.

Es gibt da eine DBTreeView Komponente, allerdings kann ich da keinen Record benutzen um Daten für jeden Node abzuspeichern (oder besser gesagt, ich wüsste nicht wie).

Wie würdet ihr das ganze sauber und performant und nicht zu kompliziert lösen, wenn ihr von Delphi 9, MSSQL 2000, der VirtualTreeView Komponente und der Datenbank mit ID, PID und Bezeichnung ausgeht?

Hoffe jemand kann mir helfen und viele Grüsse
Siles
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#2

Re: MSSQL - Problem mit Rekursiver SP

  Alt 28. Jan 2008, 16:31
Zitat von siles:
Es gibt da eine DBTreeView Komponente, allerdings kann ich da keinen Record benutzen um Daten für jeden Node abzuspeichern (oder besser gesagt, ich wüsste nicht wie).
Ich kenne deinen DBTreeView jetzt nicht, aber es ist in aller Regel so, dass man über Properties einstellen kann, welchen Namen das ID-Feld und das Parent-ID-Feld hat.
Zusätzlich gibt man noch den Feldnamen an, den das DBTreeView als Knotennamen anzeigen soll.
Wenn man einen bestimmten Knoten selektiert hat, steht der aktuelle Datensatzzeiger genau auf diesem Datensatz.
Nun ist es kein Problem, über weitere DBEdit-Felder auf dem Formular diese Datenfelder anzuzeigen und auch editierbar zu machen.
Andreas
  Mit Zitat antworten Zitat
siles

Registriert seit: 14. Jan 2008
34 Beiträge
 
#3

Re: MSSQL - Problem mit Rekursiver SP

  Alt 28. Jan 2008, 16:49
Zitat von shmia:
Zitat von siles:
Es gibt da eine DBTreeView Komponente, allerdings kann ich da keinen Record benutzen um Daten für jeden Node abzuspeichern (oder besser gesagt, ich wüsste nicht wie).
Ich kenne deinen DBTreeView jetzt nicht, aber es ist in aller Regel so, dass man über Properties einstellen kann, welchen Namen das ID-Feld und das Parent-ID-Feld hat.
Zusätzlich gibt man noch den Feldnamen an, den das DBTreeView als Knotennamen anzeigen soll.
Wenn man einen bestimmten Knoten selektiert hat, steht der aktuelle Datensatzzeiger genau auf diesem Datensatz.
Nun ist es kein Problem, über weitere DBEdit-Felder auf dem Formular diese Datenfelder anzuzeigen und auch editierbar zu machen.
Die TreeView basiert auf dem virtualstringtree und heisst DynamicDBTreeView oder so.

Bei der normalen VirtualTreeView konnte man einen Record anlegen und so mehrere Daten einem Node zuweisen, ich weiss nicht wie das damit gehen soll weil ja nur die Namen der DB Felder: ID, PID, ChildrenId und Name als Eigenschaften angegeben werden können.
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#4

Re: MSSQL - Problem mit Rekursiver SP

  Alt 28. Jan 2008, 17:01
Zitat von siles:
Bei der normalen VirtualTreeView konnte man einen Record anlegen und so mehrere Daten einem Node zuweisen, ich weiss nicht wie das damit gehen soll weil ja nur ID, PID und der Name als Eigenschaften angegeben werden können.
Zusätzlich zu diesen Properties muss es ja noch ein DataSource Property geben, damit wird eine Query oder Table an das DBTreeView angebunden.
Wie oben gesagt, wenn du im DBTreeView einen bestehenden Knoten anklickst, da steht das Dataset genau auf diesem Datensatz.
Das DBTreeView übernimmt hier die Aufgabe eines DBNavigators.
Das Ändern von Daten geht dann so:
Delphi-Quellcode:
Query1.Edit;
Query1['User'] := aktuellerUser;
Query1['LastChange'] := Now;
Query1.Post;
Das Löschen des aktuellen Knotens ist auch einfach:
query1.Delete; Das Einfügen eines neuen Kindknoten ist etwas schwieriger, weil man dazu eine neue ID benötigt.
Mit folgender SQL-Abfrage kann man sich diese ID besorgen.
SELECT Max(ID)+1 AS NewID FROM Tabelle Zusätzlich benötigt man noch die ParendID - diese lässt sich höchstwahrscheinlich über das DBTreeView erhalten
; das Property könnte ParentValue oder so ähnlich heisen. (dieses Property ist readonly und deshalb im OI unsichtbar)
Andreas
  Mit Zitat antworten Zitat
siles

Registriert seit: 14. Jan 2008
34 Beiträge
 
#5

Re: MSSQL - Problem mit Rekursiver SP

  Alt 28. Jan 2008, 17:08
Zitat von shmia:
Zitat von siles:
Bei der normalen VirtualTreeView konnte man einen Record anlegen und so mehrere Daten einem Node zuweisen, ich weiss nicht wie das damit gehen soll weil ja nur ID, PID und der Name als Eigenschaften angegeben werden können.
Zusätzlich zu diesen Properties muss es ja noch ein DataSource Property geben, damit wird eine Query oder Table an das DBTreeView angebunden.
Wie oben gesagt, wenn du im DBTreeView einen bestehenden Knoten anklickst, da steht das Dataset genau auf diesem Datensatz.
Das DBTreeView übernimmt hier die Aufgabe eines DBNavigators.
Das Ändern von Daten geht dann so:
Delphi-Quellcode:
Query1.Edit;
Query1['User'] := aktuellerUser;
Query1['LastChange'] := Now;
Query1.Post;
Das Löschen des aktuellen Knotens ist auch einfach:
query1.Delete; Das Einfügen eines neuen Kindknoten ist etwas schwieriger, weil man dazu eine neue ID benötigt.
Mit folgender SQL-Abfrage kann man sich diese ID besorgen.
SELECT Max(ID)+1 AS NewID FROM Tabelle Zusätzlich benötigt man noch die ParendID - diese lässt sich höchstwahrscheinlich über das DBTreeView erhalten
; das Property könnte ParentValue oder so ähnlich heisen. (dieses Property ist readonly und deshalb im OI unsichtbar)
Ah! Ich dachte der holt sich die Daten nur aus der Datenbank, zeichnet den Tree und hat dann nichts mehr mit der Datenbank zu tun.
Wenn das so ist könnte ich diese vermutlich doch verwenden! Ich schaue mir es nochmals genauer an - morgen.

Vielen herzlichen Dank schonmal!
  Mit Zitat antworten Zitat
omata

Registriert seit: 26. Aug 2004
Ort: Nebel auf Amrum
3.154 Beiträge
 
Delphi 7 Enterprise
 
#6

Re: MSSQL - Problem mit Rekursiver SP

  Alt 28. Jan 2008, 17:37
Hallo siles,

schau auch mal hier.

Edit: Ups, du hattest ja den Link oben angegeben. Schau dir aber dort trotzdem mal den Post #5 an.

Gruss
Thorsten
  Mit Zitat antworten Zitat
siles

Registriert seit: 14. Jan 2008
34 Beiträge
 
#7

Re: MSSQL - Problem mit Rekursiver SP

  Alt 28. Jan 2008, 18:00
Zitat von omata:
Hallo siles,

schau auch mal hier.

Edit: Ups, du hattest ja den Link oben angegeben. Schau dir aber dort trotzdem mal den Post #5 an.

Gruss
Thorsten
Hallo Thorsten.
Die Stored Procedure aus Post 5 habe ich heute auch schon auf meine Anwendung angepasst und erstellt, ich bekomme dann beim ausführen der SP mit der PID als Argument alle ihm untergeordneten Nodes (Childs) zurück.
Ich habe es leider nicht fertig gebracht, diese dann in die TreeView zu bringen, hatte jedesmal ein Blackout wenn ich mich in die Sache eindenken wollte

Ich könnte mir denken, ich müsste erst mal in nem Query alle Notes auf Root abfragen und für jeden davon die Storedprocedure ausführen um alle ihre Subnodes und Sub-Subnodes etc. herauszubekommen.
Dann stösst es jedoch schon an. Wie ich diese dann mit welchen Schleifen in die TreeView befordere ist mir irgendwie grad zu kompliziert
  Mit Zitat antworten Zitat
omata

Registriert seit: 26. Aug 2004
Ort: Nebel auf Amrum
3.154 Beiträge
 
Delphi 7 Enterprise
 
#8

Re: MSSQL - Problem mit Rekursiver SP

  Alt 28. Jan 2008, 18:08
Hier mal ein Beispiel...

Delphi-Quellcode:
procedure fillTreeview(Tree:TTreeview; SQLConnection:TSQLConnection);

  procedure fill(Depth:integer; ANode:TTreeNode; SDS:TSimpleDataSet);
  var abbruch:boolean;
      Node:TTreeNode;
  begin
    abbruch:=false;
    while not SDS.Eof and not abbruch do begin
      Node:=Tree.Items.AddChild(
        ANode,
        SDS.FieldByName('nodename').AsString
      );
      SDS.Next;
      if SDS.FieldByName('depth').AsInteger > Depth then
        fill(Depth+1, Node, SDS);
      if SDS.FieldByName('depth').AsInteger < Depth then
        abbruch:=true;
    end;
  end;

var SDS:TSimpleDataSet;
begin
  SDS:=TSimpleDataSet.Create(nil);
  try
    Tree.Items.BeginUpdate;
    Tree.Items.Clear;
    SDS.Connection:=SQLConnection;
    SDS.DataSet.CommandType:=ctStoredProc;
    SDS.DataSet.CommandText:=
      'GetSortedSubTree';
    SDS.DataSet.ParamByName('nodeid').AsInteger:=1;
    SDS.Open;
    fill(SDS.FieldByName('depth').AsInteger, nil, SDS);
    SDS.Close;
  finally
    SDS.free;
    Tree.Items.EndUpdate;
  end;
end;
Aufruf...
  fillTreeview(TreeView, SQLConnection); Gruss
Thorsten
  Mit Zitat antworten Zitat
siles

Registriert seit: 14. Jan 2008
34 Beiträge
 
#9

Re: MSSQL - Problem mit Rekursiver SP

  Alt 28. Jan 2008, 18:15
Zitat von omata:
Hier mal ein Beispiel...

Delphi-Quellcode:
procedure fillTreeview(Tree:TTreeview; SQLConnection:TSQLConnection);

  procedure fill(Depth:integer; ANode:TTreeNode; SDS:TSimpleDataSet);
  var abbruch:boolean;
      Node:TTreeNode;
  begin
    abbruch:=false;
    while not SDS.Eof and not abbruch do begin
      Node:=Tree.Items.AddChild(
        ANode,
        SDS.FieldByName('nodename').AsString
      );
      SDS.Next;
      if SDS.FieldByName('depth').AsInteger > Depth then
        fill(Depth+1, Node, SDS);
      if SDS.FieldByName('depth').AsInteger < Depth then
        abbruch:=true;
    end;
  end;

var SDS:TSimpleDataSet;
begin
  SDS:=TSimpleDataSet.Create(nil);
  try
    Tree.Items.BeginUpdate;
    Tree.Items.Clear;
    SDS.Connection:=SQLConnection;
    SDS.DataSet.CommandType:=ctStoredProc;
    SDS.DataSet.CommandText:=
      'GetSortedSubTree';
    SDS.DataSet.ParamByName('nodeid').AsInteger:=1;
    SDS.Open;
    fill(SDS.FieldByName('depth').AsInteger, nil, SDS);
    SDS.Close;
  finally
    SDS.free;
    Tree.Items.EndUpdate;
  end;
end;
Aufruf...
  fillTreeview(TreeView, SQLConnection); Gruss
Thorsten
Vielen Dank Thorsten. Ich sehe zwar auf Anhieb keinen wirklichen Unterschied zum Code den du bei der SP verwendet hast, die den gesamten Tree liefert, aber vielleicht komme ich morgen darauf.

Ach ja etwas musste ich andes machen und zwar konnte ich nicht die DBExpress Komponenten verwenden..das SimpleDataSet meldet einen Fehler wegen des Cursors.
Habe stattdessen die Ado Komponenten benutzt und diese direkt im GUI erstellt und nicht im Code. Denke aber nicht dass das etwas ausmacht.
  Mit Zitat antworten Zitat
omata

Registriert seit: 26. Aug 2004
Ort: Nebel auf Amrum
3.154 Beiträge
 
Delphi 7 Enterprise
 
#10

Re: MSSQL - Problem mit Rekursiver SP

  Alt 28. Jan 2008, 18:32
Hier mal ein Beispiel mit ADO...

Delphi-Quellcode:
procedure fillTreeview(Tree:TTreeview; ADOConnection:TADOConnection);

  procedure fill(Depth:integer; ANode:TTreeNode; ADOStoredProc:TADOStoredProc);
  var abbruch:boolean;
      Node:TTreeNode;
  begin
    abbruch:=false;
    while not ADOStoredProc.Eof and not abbruch do begin
      Node:=Tree.Items.AddChild(
        ANode,
        ADOStoredProc.FieldByName('nodename').AsString
      );
      ADOStoredProc.Next;
      if ADOStoredProc.FieldByName('depth').AsInteger > Depth then
        fill(Depth+1, Node, ADOStoredProc);
      if ADOStoredProc.FieldByName('depth').AsInteger < Depth then
        abbruch:=true;
    end;
  end;

var ADOStoredProc:TADOStoredProc;
begin
  ADOStoredProc:=TADOStoredProc.Create(nil);
  try
    Tree.Items.BeginUpdate;
    Tree.Items.Clear;
    ADOStoredProc.Connection:=ADOConnection;
    ADOStoredProc.ProcedureName:='GetSortedSubTree;1';
    ADOStoredProc.Parameters.Refresh;
    ADOStoredProc.Parameters.ParamByName('@NodeID').Value:=1;
    ADOStoredProc.Open;
    fill(ADOStoredProc.FieldByName('depth').AsInteger, nil, ADOStoredProc);
    ADOStoredProc.Close;
  finally
    ADOStoredProc.free;
    Tree.Items.EndUpdate;
  end;
end;
Gruss
Thorsten
Angehängte Dateien
Dateityp: zip dbtree_816.zip (29,1 KB, 7x aufgerufen)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:08 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