Autor Beitrag
Peter18
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 489
Erhaltene Danke: 2


Delphi4
BeitragVerfasst: Di 18.03.14 19:17 
Ein freundliches Hallo an alle,

und wieder ein neues Problem! Nachdem es endlich gelungen ist eine Datenbank-Tabelle zu öffnen, möchte ich die Namen der vorhandenen Tabellen auflisten. Ein VBA-Beispiel konnte ich jedoch noch nicht umsetzen. Ich tue ich mich etwas schwer mit den Schnittstellen, aber es wird.

Mein Problem:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
function TADODataSet.GetLstOfTables: TStringList;
var
  I : Integer;

begin
  if not Assigned(ADORecordset) then
  begin
    ADORecordSet                := CoRecordSet.Create;  // Warscheinlich nicht nötig
    ADORecordSet.CursorLocation := adUseClient;         // Warscheinlich nicht nötig
    ADORecordSet                := OpenSchema( adSchemaTables, nilnil);
  end;
  Result := TStringList.Create;
  for I := 0 to ADORecordSet.Fields.Count-1 do
  begin
    Result.Add( ADORecordSet.Fields[I].Name );
  end;
end;

Obwohl "OpenSchema" in der "ADODB_TLB" eingetragen ist, wird die Funktion als "undefinierter Bezeichner" angemeckert.

Ich hoffe jemand hat einen Tipp, der mich weiter bringt. Es scheint aber keine Methode des Recordsets zu sein.

Grüße von der Nordsee

Peter
Peter18 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 489
Erhaltene Danke: 2


Delphi4
BeitragVerfasst: Di 18.03.14 19:55 
Ein freundliches Hallo an alle,

ich muß die Frage anders stellen:
ausblenden Delphi-Quelltext
1:
      ADORecordSet                := ADOConnection.OpenSchema( adSchemaTables, 00);					

Mit dieser Zeile meckert der Compiler nicht mehr, aber zur Laufzeit nölt der Rechner über die Parameter. "Schema: SchemaEnum; Restrictions: OleVariant; SchemaID: OleVariant" sind die, die ich auf 0 gesetzt habe.
ausblenden Delphi-Quelltext
1:
ADOConnection.OpenSchema( adSchemaTables, 'TABLE_NAME''TABLE_NAME');					

funktioniert auch nicht. Bei MS scheinen die Parameter in anderer Reihenfolge zu stehen. Mit konstanter Bosheit kommt die gleiche Fehlermeldung.

Hoffe jemand hat einen Tipp.

Grüße von der Nordsee

Peter
baumina
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 305
Erhaltene Danke: 61

Win 7
Delphi 10.2 Tokyo Enterprise
BeitragVerfasst: Mi 19.03.14 09:01 
Da keiner weiß was deine spezielle ADO-Variante für Parameter erwartet beim OpenShema, wird dir hier auch keiner weiterhelfen können. Die OpenSchema-Procedure der delphieigenen TADOConnection würde nämlich folgende Parameter erwarten:

ausblenden Delphi-Quelltext
1:
procedure OpenSchema(const Schema: TSchemaInfo; const Restrictions: OleVariant;  const SchemaID: OleVariant; DataSet: TADODataSet);					
WasWeißDennIch
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 653
Erhaltene Danke: 160



BeitragVerfasst: Mi 19.03.14 09:18 
OpenSchema, aber das ist nur eine Vermutung.
Perlsau
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mi 19.03.14 10:02 
user profile iconPeter18 hat folgendes geschrieben Zum zitierten Posting springen:
Nachdem es endlich gelungen ist eine Datenbank-Tabelle zu öffnen, möchte ich die Namen der vorhandenen Tabellen auflisten.

Wie wär's mit GetTableNames?

Füllt eine Liste mit den Namen der Tabellen in der Datenbank. Mit GetTableNames können Sie eine Liste der Datenbanktabellen abrufen. List gibt das Listenobjekt an, in das die Tabellenamen eingefügt werden. In SystemTables kann angegeben werden, ob die Systemtabellen der Datenbank in die Liste der Tabellennamen aufgenommen werden sollen.
Peter18 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 489
Erhaltene Danke: 2


Delphi4
BeitragVerfasst: Mi 19.03.14 12:30 
Hallo baumina,

Danke für Deine Antwort. Aber
Zitat:
Da keiner weiß was deine spezielle ADO-Variante für Parameter erwartet

ist nicht richtig. "OpenSchema" ist eine in der "ADODB_TLB" eingetragene Funktion und damit Bestandteil der Systemschnittstelle.

Hallo WasWeißDennIch,

Auch Dir meinen Dank.
ausblenden Delphi-Quelltext
1:
function OpenSchema(Schema: SchemaEnum; Restrictions: OleVariant; SchemaID: OleVariant): _Recordset; safecall;					

sieht für mich etwas anders aus als:
ausblenden Quelltext
1:
Set recordset = connection.OpenSchema(QueryType, Criteria, SchemaID)					

Deswegen hatte ich verschiedene Varianten probiert.

Hallo Perlsau,

Dir ebenfalls Dank. Die Funktion, auf die Du Dich beziehst, wollte ich ja schreiben, da sie nicht vorhanden ist. (Delphi 4) Doch leider herrscht etwas Konfusion bei den Parametern.

Ich hoffe die Nuß ist zu knacken.

Grüße von der Nordsee

Peter
Perlsau
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mi 19.03.14 12:52 
user profile iconPeter18 hat folgendes geschrieben Zum zitierten Posting springen:
Die Funktion, auf die Du Dich beziehst, wollte ich ja schreiben, da sie nicht vorhanden ist. (Delphi 4)

Mangels Delphi 4 war mir dieser Umstand natürlich nicht bekannt ... Da weiß ich auf die Schnelle auch nicht weiter ...
Peter18 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 489
Erhaltene Danke: 2


Delphi4
BeitragVerfasst: Mi 19.03.14 13:47 
Hallo Perlsau,

trotzdem nochmals danke. Hatte sonst immer auf Delphi 4 hingewiesen aber diesmal vergessen, sorry.

Mit
ausblenden Delphi-Quelltext
1:
ADOConnection.OpenSchema( adSchemaTables, EmptyParam, EmptyParam);					

nölt er nicht mehr und liefert:
Zitat:
'TABLE_CATALOG'#$D#$A'TABLE_SCHEMA'#$D#$A'TABLE_NAME'#$D#$A'TABLE_TYPE'#$D#$A'TABLE_GUID'
'DESCRIPTION'#$D#$A'TABLE_PROPID'#$D#$A'DATE_CREATED'#$D#$A'DATE_MODIFIED'#$D#$A
.
Die Namen der Tabellen waren jedoch noch nicht dabei.

Grüße von der Nordsee

Peter
Peter18 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 489
Erhaltene Danke: 2


Delphi4
BeitragVerfasst: Mi 19.03.14 17:05 
Ein freundliches Hallo an alle,

Neue Forschungsergebnisse, auf deren Dasis vielleicht doch noch jemand einen Tipp hat. Mit
ADORecordSet := ADOConnection.OpenSchema( adSchemaTables, EmptyParam, EmptyParam);erhalte ich offensichtlich eine Tabelle.

ADORecordSet.Fields[I].Nameliefert anscheinend die Spaltenüberschrift. Doch noch ist mir nicht klar, wie ich an die Werte herankomme. Mit
ADORecordSet.Fields.item['TABLE_CATALOG']Erhalte ich anscheinend die Spalte und dann??

Die ADO Programmer's Reference ist etwas unübersichtlich und endet an dieser Stelle. Aber ich forsche weiter.

Grüße von der Nordsee

Peter
Peter18 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 489
Erhaltene Danke: 2


Delphi4
BeitragVerfasst: Do 20.03.14 11:27 
Ein freundliches Hallo an alle,

:D Ihr seht schon, es gibt positives zu berichten!

Nachdem die Tabelle sichtbar war, wurde schnell klar, wie die Sache zu handhaben ist:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
procedure TADODataSet.GetLstOfTables( var Sl : TStringList );
begin
  if IsOpen then
  begin
    if not Assigned(ADORecordset) then
    begin
      ADORecordSet                := CoRecordSet.Create;    
      ADORecordSet.CursorLocation := adUseClient;                        
    end;
    ADORecordSet := ADOConnection.OpenSchema( adSchemaTables, EmptyParam, EmptyParam);
    if Assigned( Sl ) then Sl.Clear
                      else Sl := TStringList.Create;
    while not ADORecordSet.EOF do
    begin
      if ADORecordSet.Fields.item['TABLE_TYPE'].Value = 'TABLE' then
        Sl.Add( ADORecordSet.Fields.item['TABLE_NAME'].Value );
      ADORecordSet.MoveNext;
    end;
  end;
end;

In der Spalte 'TABLE_TYPE' muß der Eintrag 'TABLE' stehen, dann handelt es sich um den Namen einer Tabelle, deren Name in der Spalte 'TABLE_NAME' zu finden ist.

Grüße von der Nordsee

Peter
WasWeißDennIch
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 653
Erhaltene Danke: 160



BeitragVerfasst: Do 20.03.14 11:40 
Das mit dem Var-Parameter würde ich mir allerdings noch einmal überlegen, da so nicht gleich ersichtlich ist, wo die Instanz angelegt wurde. Da man im Allgemeinen Objekte auf der Ebene freigeben sollte, auf der sie instanziert wurden, könnte das zu Verständnisproblemen und/oder Speicherlecks führen.
Peter18 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 489
Erhaltene Danke: 2


Delphi4
BeitragVerfasst: Do 20.03.14 12:47 
Hallo WasWeißDennIch,

Danke für Deine Anregung. Doch genau das waren die Überlegungen. So kann ich die Liste in einer Routine erstellen und sie in genau dieser Routine auch wieder auflösen. Und ich kann sie mehrfach verwenden (Clear). Wenn ich die Liste in einer Funktion erzeuge, muß ich sie auf jeden Fall auflösen, bevor ich eine neue Auflistung erstellen kann.

Grüße von der Nordsee

Peter
Perlsau
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Do 20.03.14 13:39 
WasWeißDennIch meinte aber offenbar was anderes: Du sollst die Übergabe der Stringlist nicht mit einem Var-Parameter einleiten. Die Variable, der du die Stringliste mit MeineVariable := TStringList.Create zuweist, ist ja nur ein Pointer, der auf den Beginn der Stringliste im Speicher zeigt. Übergibst du sie mit Var-Parameter, kann der Empfänger die Stringliste Freigeben. Ansonsten stellt MeineVariable eine Konstante dar, die vom Empfänger nicht verändert werden kann. Das heißt jedoch nicht, daß der Speicherbereich, auf den MeineVariable zeigt, nicht verändert werden darf, denn die Stringlist verwaltet ja diesen Speicherbereich dennoch, indem sie Items anlegt, löscht, sortiert usw.


Zuletzt bearbeitet von Perlsau am Do 20.03.14 14:57, insgesamt 1-mal bearbeitet
WasWeißDennIch
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 653
Erhaltene Danke: 160



BeitragVerfasst: Do 20.03.14 14:33 
Du kannst doch genauso gut eine außerhalb erzeugte Instanz wiederverwenden.
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
(* Das const ist nicht wirklich nötig und dient nur dem besseren Verständnis *)
function SomeFunc(const AList: TStrings);
begin
  Assert(Assigned(AList), 'Keine TStrings-Intanz übergeben');
  AList.BeginUpdate;
  try
    AList.Clear;
    (* Irgendwelche Daten in die Liste schreiben *)
  finally
    AList.EndUpdate;
  end;
end;

procedure TSomeClass.SomeEvent;
var
  List: TStringlist;
begin 
  List := TStringlist.Create;
  try
    (* beliebig oft wiederholbar *)
    SomeFunc(List);
  finally
    List.Free;
  end;
end;