Autor |
Beitrag |
Peter18
Beiträge: 489
Erhaltene Danke: 2
Delphi4
|
Verfasst: 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:
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; ADORecordSet.CursorLocation := adUseClient; ADORecordSet := OpenSchema( adSchemaTables, nil, nil); 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
Beiträge: 489
Erhaltene Danke: 2
Delphi4
|
Verfasst: Di 18.03.14 19:55
Ein freundliches Hallo an alle,
ich muß die Frage anders stellen:
Delphi-Quelltext 1:
| ADORecordSet := ADOConnection.OpenSchema( adSchemaTables, 0, 0); |
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.
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
Beiträge: 305
Erhaltene Danke: 61
Win 7
Delphi 10.2 Tokyo Enterprise
|
Verfasst: 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:
Delphi-Quelltext 1:
| procedure OpenSchema(const Schema: TSchemaInfo; const Restrictions: OleVariant; const SchemaID: OleVariant; DataSet: TADODataSet); |
|
|
WasWeißDennIch
Beiträge: 653
Erhaltene Danke: 160
|
Verfasst: Mi 19.03.14 09:18
OpenSchema, aber das ist nur eine Vermutung.
|
|
Perlsau
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Mi 19.03.14 10:02
Peter18 hat folgendes geschrieben : | 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
Beiträge: 489
Erhaltene Danke: 2
Delphi4
|
Verfasst: 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.
Delphi-Quelltext 1:
| function OpenSchema(Schema: SchemaEnum; Restrictions: OleVariant; SchemaID: OleVariant): _Recordset; safecall; |
sieht für mich etwas anders aus als:
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
|
Verfasst: Mi 19.03.14 12:52
Peter18 hat folgendes geschrieben : | 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
Beiträge: 489
Erhaltene Danke: 2
Delphi4
|
Verfasst: Mi 19.03.14 13:47
Hallo Perlsau,
trotzdem nochmals danke. Hatte sonst immer auf Delphi 4 hingewiesen aber diesmal vergessen, sorry.
Mit
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
Beiträge: 489
Erhaltene Danke: 2
Delphi4
|
Verfasst: 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
Beiträge: 489
Erhaltene Danke: 2
Delphi4
|
Verfasst: Do 20.03.14 11:27
Ein freundliches Hallo an alle,
Ihr seht schon, es gibt positives zu berichten!
Nachdem die Tabelle sichtbar war, wurde schnell klar, wie die Sache zu handhaben ist:
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
Beiträge: 653
Erhaltene Danke: 160
|
Verfasst: 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
Beiträge: 489
Erhaltene Danke: 2
Delphi4
|
Verfasst: 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
|
Verfasst: 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
Beiträge: 653
Erhaltene Danke: 160
|
Verfasst: Do 20.03.14 14:33
Du kannst doch genauso gut eine außerhalb erzeugte Instanz wiederverwenden.
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:
| function SomeFunc(const AList: TStrings); begin Assert(Assigned(AList), 'Keine TStrings-Intanz übergeben'); AList.BeginUpdate; try AList.Clear; finally AList.EndUpdate; end; end;
procedure TSomeClass.SomeEvent; var List: TStringlist; begin List := TStringlist.Create; try SomeFunc(List); finally List.Free; end; end; |
|
|