Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Indexfehler ?? (https://www.delphipraxis.net/104119-indexfehler.html)

Fritz01 27. Nov 2007 18:17

Datenbank: Absolute Database • Version: 5.14 • Zugriff über: Table / DataSource

Indexfehler ??
 
Hallo,
in meinem Prog. werden im Grid Daten angezeigt, die mit onTitleClick einen Index erhalten und sortiert im Grid erscheinen.
Delphi-Quellcode:
Table.Close;
     Table.Exclusive := true;
     Table.AddIndex(sName, sName,[]); //  (IndexName, indiziertes Feld[optionen]);
     Table.IndexName := sName;
     Table.Exclusive := False;
     Table.Open;
     sIndexList.Add(sName);  // neuer Index in StringListe
Die neu erzeugten Indizies werden in einer Liste ‚gesammelt’.
Damit die Tabelle nicht geändert wird, werden die neu erstellten Indizies gemäß dieser Liste wieder gelöscht.
Delphi-Quellcode:
Table.DeleteIndex(sIndexList[cnt]); // index aus table
   sIndexList.Delete(cnt);                     // index aus stringlist
   Table.IndexDefs.Update;           // indexdefinition aktualisieren
   Table.StoreDefs := False;
Das ist auch soweit OK.
Nun habe ich mein Prog. erweitert, die Table werden in TreeView dargestellt. Mit Click auf die entsprechende Tabelle wird die Table geöffnet, die Daten im Grid angezeigt und man kann so zwischen den Tabellen hin und her schalten. Auch OK.
Aber clicke ich im Grid und erstelle so einen neuen Index zb. Name, der vor dem Tabellenwechsel wieder gelöscht wird, so erscheint bei Tabellenwechsel die Fehlermeldung Cannot find index NAME
Der Tabellenwechsel: Index der aktiven Table löschen, aktive Tabelle schließen (Table.Close), neue Tabelle öffnen.
Delphi-Quellcode:
SelectTable(TreeView.Selected.Text);
    Table.Close;                                                        // active Table schließen
    Table.TableName := TreeView.Selected.Text; // neue Tabelle
    Table.Open;
Warum wird da ein nicht mehr vorhandenr Index gesucht, wo liegt da eventuell der Fehler?
Habe schon einige Zeit mit Fehlersuche verbracht und nichts gefunden, vielleicht hat ja von Euch eine eine hilfreiche Idee dazu. Danke
Fritz aus Ahlhorn

Fritz01 27. Nov 2007 20:33

Re: Indexfehler ??
 
Hallo nochmal,
habe in der Zwischenzeit noch gesucht.

Der Tabellenwechsel: Index der aktiven Table löschen, aktive Tabelle schließen (Table.Close), neue Tabelle öffnen.

Delphi-Quellcode:
procedure TfrmMain.TreeViewChange(Sender: TObject; Node: TTreeNode);
begin
  if TreeView.Selected.IsFirstNode then exit
  else
  begin              
    SelectTable(TreeView.Selected.Text);
    Table.Close;                      // active Table schließen
    Table.TableName := TreeView.Selected.Text; // neue TabellenName

    Table.Open;        <================== Hier liegt der Fehler
   
    iRecordCount.Caption := IntToStr(Table.RecordCount); // Datensätze zählen und anzeigen
  end;
end;
Da muß doch noch ein Index der alten Tabelle sein, der in der neuen Tabelle nicht vorhanden ist.
Wie kriege ich den da weg, was muß ich da machen?
Fritz

raiguen 27. Nov 2007 21:19

Re: Indexfehler ??
 
Zitat:

Zitat von Fritz01
Da muß doch noch ein Index der alten Tabelle sein, der in der neuen Tabelle nicht vorhanden ist.
Wie kriege ich den da weg, was muß ich da machen?Fritz

Nach dem Table.Close auf jeden Fall Table.IndexName := '' setzen ;)

Delphi-Quellcode:
procedure TfrmMain.TreeViewChange(Sender: TObject; Node: TTreeNode);
begin
  if TreeView.Selected.IsFirstNode then exit
  else
  begin              
    SelectTable(TreeView.Selected.Text);
    Table.Close;                      // active Table schließen
    Table.IndexName := ''; // <<---hier könnte noch ein zugewiesener Index vom Vorgänger drin sein!Deswegen erstmal blank machen ;)
    Table.TableName := TreeView.Selected.Text; // neue TabellenName

    Table.Open;     //--wird mit dem PrimärIndex(sofern vorhanden) geöffnet
    //--für die neue Tabelle sicherheitshalber mal die Indexliste aktualisieren
    Table.IndexDefs.Update;
    Table.StoreDefs := false;
    iRecordCount.Caption := IntToStr(Table.RecordCount); // Datensätze zählen und anzeigen
  end;
end;
Was verbirgt sich hinter der Funktion/Prozedur SelectTable()?

Fritz01 27. Nov 2007 23:26

Re: Indexfehler ??
 
Hallo,
ist schon spät geworden.
Habe es mal so gemacht und es hat sich nur etwas verändert.
Die erste Tabelle wird geöffnet, ein Index auf PLZ und Index gelöscht.
Eine Andere läßt sich nun öffnen, aber kommt dann der Click für den Index kommt die Fehlermeldung: Zugriffsverletzung
Ich kriegs nicht gebacken, aber nur nicht aufgeben!

Zitat:

Was verbirgt sich hinter der Funktion/Prozedur SelectTable()?
Delphi-Quellcode:
procedure TfrmMain.SelectTable(Name: String='');
var
 i: Integer;            
begin
  if (name <> '') then for i:=1 to TreeView.Items.Count-1 do
  if AnsiUpperCase(TreeView.Items[i].Text) = AnsiUpperCase(Name) then
  begin
    TreeView.Selected := TreeView.Items[i];
    Break;
  end;
end;
Erst mal genug für heute, morgen werde ich weitersehen.
Fritz

marabu 28. Nov 2007 08:28

Re: Indexfehler ??
 
Hallo Fritz,

vom Prinzip her solltest du folgende Struktur verwenden können:

Delphi-Quellcode:
unit DemoFrm;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DB, ABSMain, Grids, DBGrids, ComCtrls;

type
  TDemoForm = class(TForm)
    TreeView: TTreeView;
    DBGrid: TDBGrid;
    ABSDatabase: TABSDatabase;
    ABSTable: TABSTable;
    DataSource: TDataSource;
    procedure TreeViewChange(Sender: TObject; Node: TTreeNode);
    procedure DBGridTitleClick(Column: TColumn);
  private
    procedure SwitchTable(const tblName: string);
    procedure SwitchIndex(const idxName: string);
  end;

var
  DemoForm: TDemoForm;

implementation

{$R *.dfm}

uses
  StrUtils;

procedure TDemoForm.SwitchIndex(const idxName: string);
begin
  with AbsTable do
  if not SameText(idxName, IndexFieldNames) then
  begin
    DisableControls;
    try
      IndexFieldNames := idxName;
    finally
      EnableControls;
    end;
  end;
end;

procedure TDemoForm.SwitchTable(const tblName: string);
begin
  with AbsTable do
  if not SameText(tblName, TableName) then
  begin
    DisableControls;
    try
      if Active then Close;
      SwitchIndex('');
      TableName := tblName;
      if TableName <> '' then Open;
    finally
      EnableControls;
    end;
  end;
end;

procedure TDemoForm.TreeViewChange(Sender: TObject; Node: TTreeNode);
begin
  SwitchTable(IfThen(Assigned(Node), Node.Text));
end;

procedure TDemoForm.DBGridTitleClick(Column: TColumn);
begin
  SwitchIndex(Column.FieldName);
end;

end.
Getippt und nicht getestet.

Freundliche Grüße

Fritz01 28. Nov 2007 12:39

Re: Indexfehler ??
 
Hallo marabu,
habe Deinen Text mal so übernommen um zu schauen was da passiert.
Nach OpenDialog und procedure (siehe #4) erscheint in der TreeView 'Demo.Abs mit einem + davor.
Mit dem ersten Click in TreeView erscheint die Fehlermeldung Table Demo.Abs not exists
ABSDatabase hat den Namen Demo.abs, eine Table Demo.abs gibt es wirklich nicht.
Was ist das ?
Gruß
Fritz

Fritz01 28. Nov 2007 18:17

Re: Indexfehler ??
 
@ marabu
Hallo Achim,
habe Deinen Code versucht zu verstehen. Die mit * gezeichneten Zeilen habe ich bei 'SwitchTable' hinzu gefügt. Das ist nun OK, hat aber einen kleinen Schönheitsfehler: wenn zb. 3 Einträge in TreeView sind kann man den ersten Eintrag nicht öffnen. Clickt man den 2. oder den 3. Eintrag an, kann man danach auch den 1. öffnen. Mal sehen.Vielleicht finde ich da ja noch was.

Delphi-Quellcode:
begin
*  if TreeView.Selected.IsFirstNode then exit  
*  else
  begin
    with Table do
Bei 'SwitchIndex' kann ich nur bereits vorhandene Indizies nutzen! (Aber der Tabellenwechsel ist OK.)
Clicke ich aber auf einen Titel, bei dem kein Index vorhanden ist wird das Prog mit eine Fehlermeldung beendet.
Es sollte so sein: Ist ein Index vorhanden, diesen auch benutzen. Ist kein Index da, so sollte ein neuer Index für dieses Feld erstellt werden. Damit am Ende die Table nicht verändert ist muß der neu erstellte Index entweder mit dem nächsten TitleClick oder vor SwitchTable gelöscht werden. Weiß nich so recht wie ich das in SwitchTable unterbringen kann. Mal sehen.
Mit den besten Grüßen aus Ahlhorn
Fritz

mkinzler 28. Nov 2007 18:30

Re: Indexfehler ??
 
Ich würde die Logik umdrehen:
Delphi-Quellcode:
if not TreeView.Selected.IsFirstNode then
begin
   ...
end;

Fritz01 28. Nov 2007 18:44

Re: Indexfehler ??
 
Hallo mkinzler,
danke für den Hinweis, aber was bringt das? Habs gemacht, sehe darin keinen Vorteil und ich muß trotzdem um den ersten Eintrag zu öffnen zuerst auf den 2. oder 3. Clicken. Danach geht alles. Vielleicht ein Tipp wie man sofort den ersten öffnen kann?
Mit freundlichem Gruß
Fritz

hoika 29. Nov 2007 10:03

Re: Indexfehler ??
 
Hallo,

du darfst Table.Refresh nicht vergessen vor dem Table.Open.


Heiko

Fritz01 29. Nov 2007 11:52

Re: Indexfehler ??
 
Hallo,
die Sache mit dem in #7 genannten 'Schönheitsfehler' hat sich erledigt. Kann auch nicht nachvollziehen warum das nun so ist. Liegt auch nicht an Table.Refresh !
Bleibt 'nur' noch das Problem mit SwitchIndex wie in #7 schon beschrieben. Da komme ich einfach nicht weiter. Hoffe mal wieder auf Euere Hilfe.
Übrigens: AbsoluteDatabase 5.15 ist verfügbar.
Mit freundlichem Gruß
Fritz

marabu 29. Nov 2007 12:13

Re: Indexfehler ??
 
Hallo Fritz,

ich hatte angenommen, dass beim Setzen von IndexFieldNames (anstelle von IndexName) das ständige Erzeugen und Vernichten von Index-Dateien entfallen kann. Wenn dem nicht so ist, dann muss ich die beiden Switch-Prozeduren noch etwas erweitern. Die Kunst dabei liegt darin es so zu tun, dass du den "unnötigen" Code beim Wechsel auf einen freien SQL-Server über bedingte Kompilierung abschalten kannst.

Freundliche Grüße

Fritz01 29. Nov 2007 14:49

Re: Indexfehler ??
 
Hallo Achim,
habe schon in Sachen Index einige Zeit verbracht, alles vergeblich.
Wie schon geschrieben: Ist ein Index vorhanden, diesen auch benutzen. Ist kein Index da, so sollte ein neuer Index für dieses Feld erstellt werden.
Damit am Ende die Table nicht verändert ist müssen die neu erstellten Indizies vor oder in SwitchTable gelöscht werden. Für die Erweiterung der Proceduren wäre ich dankbar.
Mit freundlichem Gruß
Fritz

Fritz01 30. Nov 2007 22:45

Re: Indexfehler ??
 
Hallo schon wieder,
Neues von Fritz!
Die Sache beschäftigt mich immer noch und auch mit Erfolg.
Im Prinzip ist es eigentlich so geblieben. Schaut das doch bitte mal an.

Wenn nicht vorhanden: Index neu

Delphi-Quellcode:
//------------------- 2) Index nicht vorhanden
   else              //
   begin
     tTable.CLose;
     tTable.Exclusive := true;
     tTable.AddIndex(idxName, idxName,[]);
     tTable.IndexName := idxName;
     tTable.Exclusive := False;
     tTable.Open;
     label3.Caption := '';
     label3.Caption := idxName;     <- nur zur Anzeige    
     sIndexList.Add(idxName);
     bIndexDelete.Enabled := True;
     //--internes Array mit den Indexdefinitionen aktualisieren
     tTable.IndexDefs.Update;
     //--evtl. Speichern der Definitionen verhindern
     tTable.StoreDefs := False;
 end;
Wenn Index nicht mehr benötigt: Index erntfernen
wird z.Zt. noch per Click gemacht

Delphi-Quellcode:
procedure TfrmMain.bIndexDeleteClick(Sender: TObject);
var
 cnt : integer;
begin
 for cnt := ListBox.Count -1 downto 0 do begin
   tTable.DeleteIndex(sIndexList[cnt]); // index aus table  
   sIndexList.Delete(cnt);       // index aus stringlist
   tTable.IndexName := '';       // falls da noch was ist
   tTable.IndexDefs.Update;      // indexdefinition aktualisieren
   tTable.StoreDefs := False;    //speichern der definitionen verhindern
   bIndexDelete.Enabled := False;
 end;
end;
Das funktioniert auch wenn in TreeView Table gewechselt wird.

Delphi-Quellcode:
procedure TfrmMain.TreeViewChange(Sender: TObject; Node: TTreeNode);
begin
  if TreeView.Selected.IsFirstNode then exit
  else
  begin              // angeclickte Tabelle öffnen und Daten in Grid zeigen
    SelectTable(TreeView.Selected.Text);               // neuer TableName
//    DisableControls;                   <-[Fehler] uMain.pas(147): Undefinierter Bezeichner:
    try              
      tTable.Close; // active Table schließen
//     <==========      hier sollte die procedure Index löschen eigefügt werden
      tTable.IndexName := '';
      tTable.TableName := TreeView.Selected.Text; // neue Tabelle
      tTable.Open;
    finally            
//     EnableControls;                  <-[Fehler] uMain.pas(147): Undefinierter Bezeichner:
    end;
    Label1.Caption:=TreeView.Selected.Text;
    tTable.IndexDefs.Update;
    tTable.StoreDefs := false;                                                  // neue Tabelle öffnen
    iRecordCount.Caption := IntToStr(tTable.RecordCount); // Datensätze zählen und anzeigen
  end;
end;
Soviel dazu!
Und hier mein Anliegen

1) DisableControls / EnableControls gibt Fehlermeldung: undefinierter Bezeichner ???
2) Die procedure bIndexDeleteClick würde ich gerne ind der procedure TreeViewChange unterbringen.
wie geht das, habs noch nie gemacht!
Danke
Fritz

raiguen 2. Dez 2007 13:33

Re: Indexfehler ??
 
zu 1) DisableControls bzw EnableControls ist eine Methode von TDataSet.
Das ständige Neuzeichnen der Bildschirmnanzeige von datensensitive Steuerlemeneten (DBGrid. DBEdit, etc) bei grossen Datenmengen ist zeitaufwändig; DisbaleControls 'friert' die Anzeige ein und nach dem Aktualisieren (in deinem Fall das Wechseln der Tabelle) wird durch EnableControls die Anzeige auf den neuesten Stand gebracht.

zu 2)
Delphi-Quellcode:
procedure TfrmMain.TreeViewChange(Sender: TObject; Node: TTreeNode);
var cnt: Integer;
begin
  if TreeView.Selected.IsFirstNode then exit
  else
  begin              // angeclickte Tabelle öffnen und Daten in Grid zeigen
    SelectTable(TreeView.Selected.Text);               // neuer TableName
    //--Anzeige im Grid 'einfrieren
    DBGrid1.DataSource.DataSet.DisableControls;
    {oder vereinfacht:}
    tTable.DisableControls;
    try              
      tTable.Close;                             // active Table schließen
      tTable.IndexName := '';                   // falls da noch was ist    
      //--alle Indizes löschen
      for cnt := sIndexList.Count -1 downto 0 do
        tTable.DeleteIndex(sIndexList[cnt]);    // index aus table
 
      sIndexList.Clear;                         // stringliste komplett leeren

      tTable.IndexDefs.Update;                  // indexdefinition aktualisieren
      tTable.StoreDefs := False;                //speichern der definitionen verhindern
     
      tTable.TableName := TreeView.Selected.Text; // neue Tabelle
      tTable.Open;
    finally            
      DBGrid1.DataSource.DataSet.EnableControls;
      {oder vereinfacht:}
      tTable.EnableControls;                  
    end;
    Label1.Caption:=TreeView.Selected.Text;
    iRecordCount.Caption := IntToStr(tTable.RecordCount); // Datensätze zählen und anzeigen
  end;
end;
Ich habe die Löschroutine stark vereinfacht (wie ich es ja schon mal vorgeschlagen habe ;) )

Fritz01 2. Dez 2007 15:47

Re: Indexfehler ??
 
@ raiguen,
danke für Deine Mithilfe, das hat sich aber in der Zwischenzeit erledigt.
Die Lösung sieht so aus, im Prinzip wie Dein Vorschlag:
Delphi-Quellcode:
procedure TfrmMain.TreeViewChange(Sender: TObject; Node: TTreeNode);
begin
  with tTable do
  if TreeView.Selected.IsFirstNode then exit
  else
  begin              // angclickte Tabelle öffnen und Daten in Grid zeigen
    SelectTable(TreeView.Selected.Text); // neuer TableName
    DisableControls;
    try
      if Active then Close;   // active Table schließen
        IndexDelete(sIndexList); // procedure IndexDelete
        TableName := TreeView.Selected.Text; // neue Tabelle
        If TableName <> '' then Open;
    finally
      EnableControls;
    end;
    Label1.Caption:=TreeView.Selected.Text;
    IndexDefs.Update;
    StoreDefs := false;                                 // neue Tabelle öffnen
    iRecordCount.Caption := IntToStr(tTable.RecordCount); // Datensätze zählen und anzeigen
  end;
end;
und die procedure IndexDelete:
Delphi-Quellcode:
 procedure TfrmMain.IndexDelete(sIndexList: Tstringlist);
var
  cnt : integer;
begin
  with tTable do
    for cnt := sIndexList.Count -1 downto 0 do begin  //sIndexList
    DeleteIndex(sIndexList[cnt]);        // index aus table (sIndexList[cnt])
    tTable.IndexDefs.Update;              // indexdefinition aktualisieren
    IndexFieldNames := '';
    IndexName := '';
  end;
  tTable.StoreDefs := False;      //speichern der definitionen verhindern
  sIndexList.Clear;
end;
Weiter habe ich hinzugefügt:
Delphi-Quellcode:
procedure TfrmMain.FormClose(Sender: TObject; var Action: TCloseAction);
begin
IndexDelete(sIndexList); // procedure IndexDelete
end;
So werden erstellte Indizies beim Beenden auch noch entfernt.
Ich denke das Thema ist damit beendet.
Nochmal danke für die Mithilfe und noch einen schönen Abend.
Fritz

raiguen 2. Dez 2007 18:30

Re: Indexfehler ??
 
Jo, wir helfen doch gerne, vor allem dann, wenn der Hilfesuchende auch aktiv an der Lösung seines Problems mitarbeitet :-D
Bezüglich deiner IndexLösch-Prozedure darf ich zum Anschluss noch eine Änderung anbringen (ich weiss, ich bin penetrant-nervig :roll: )
Delphi-Quellcode:
procedure TfrmMain.IndexDelete(sIndexList: Tstringlist);
var
  cnt : integer;
begin
  with tTable do
    IndexName := '';
    {IndexName setzen reicht aus, da IndexName und IndexFieldName sich gegenseitig ausschliessen
    IndexFieldNames := '';}

    //** diese Minimalschleife ist ausreichend, alle temp. erstellten Indizes zu löschen
    for cnt := sIndexList.Count -1 downto 0 do  //sIndexList
      DeleteIndex(sIndexList[cnt]);        // index aus table (sIndexList[cnt])
   ***//
    {in einer Schleife nicht sinnvoll, da JEDESMAL die Indizes neu ausgelesen werden,
     aber zum Schluss auf jeden Fall}
    IndexDefs.Update;              // indexdefinition aktualisieren
    //--evtl. ist das hier auch möglich, da für die aktuelle Tabelle ja nicht mehr benötigt wird
    //-- und die Indizes für die neue Tabelle ja neu eingelesen werden
    IndexDefs.Clear {bin mir z.Zt. nicht ganz sicher, ob diese MEthode vorhanden ist} 
    StoreDefs := False;      //speichern der definitionen verhindern
  end;
  sIndexList.Clear;
end;
Ansonsten weiterhin viel Erfolg und einen schönen Rest-(1.Advents)Abend


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:49 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