Hallo Entwickler,<p>in meinem Programm soll einem TIBSQL-Object zur Laufzeit ein beliebiger SQL-String zugewiesen werden. Nach dem erfolgreichen Ausführen, sollen dann alle Feld-Werte in eine TStringslist kopiert werden. Nun gibt es ja bei TIBSQL kein FieldCount. Hat jemand einen Vorschlag? (TIBQUERY wollte ich nicht verwenden, da ich diese Procedure sehr oft aufrufe und TIBSQL ja schneller ist)<p>Vielen Dank und Gruß, Andreas
Announcement
Collapse
No announcement yet.
TIBSQL und Fieldcount
Collapse
X
-
Hi,
Ermittel die Feldnamen doch direkt. Z.B.
<pre>
procedure GetIBFields( const IBFields: TStrings; const sTableName: String );
Var SysIB: TIBSQL;
begin
IBFields.Clear;
Try
SysIB := TIBSQL.Create( MainForm );
SysIB.Transaction.StartTransaction;
SysIB.SQL.Add( 'select RDB$RELATION_FIELDS.RDB$FIELD_NAME');
SysIB.SQL.Add( 'from RDB$RELATION_FIELDS');
SysIB.SQL.Add( 'where ( (RDB$RELATION_FIELDS.RDB$RELATION_NAME='''+sTableN ame+'''))');
SysIB.ExecQuery;
while not SysIB.eof do
Begin
IBFields.Add( Trim( SysIB.FieldByName('RDB$FIELD_NAME').AsString ) );
SysIB.next;
end;
SysIB.Transaction.Commit;
except
end;
end;
</pre>
Gruß
Gesin
Comment
-
Hi Andreas,
Sofern Du auf existierende Views zugreifst, liefert die folgende Prozedur Feldnamen und Tabellennamen. Den Initialisierungsklimbim für SysIB hast Du dann bereits ausserhalb der Prozedur vorgenommen.
<pre>
procedure GetIBFields( const FieldNames, TableNames: TStrings; const sTableName: String );
begin
FieldNames.Clear;
TableNames.Clear;
Try
SysIB.Close;
SysIB.SQL.Add( 'select RR.RDB$BASE_FIELD AS FIELDNAME, RV.RDB$RELATION_NAME AS TABLENAME');
SysIB.SQL.Add( 'from RDB$RELATION_FIELDS RR join RDB$VIEW_RELATIONS RV on RR.RDB$VIEW_CONTEXT=RV.RDB$VIEW_CONTEXT and RR.RDB$RELATION_NAME=RV.RDB$VIEW_NAME');
SysIB.SQL.Add( 'where ( (RDB$RELATION_FIELDS.RDB$RELATION_NAME='''+sTableN ame+'''))');
SysIB.ExecQuery;
while not SysIB.eof do
Begin
FieldNames.Add( Trim( SysIB.FieldByName('FIELDNAME').AsString ) );
TableNames.Add( Trim( SysIB.FieldByName('TABLENAME').AsString ) );
SysIB.next;
end;
except
end;
end;
</pre>
Möchtest Du die Sache im Laufzeitverhalten weiter optimieren und den SQL-String nicht jedesmal zusammenbasteln, dann arbeitest Du mit einer parametrisierten Form. Dazu setzt Du den SQL-String von SsyIB ebenfalls ausserhalb der Funktion.
<pre>
procedure InitSysIB;
begin
.
.
.
SysIB.SQL.Add( 'select RR.RDB$BASE_FIELD AS FIELDNAME, RV.RDB$RELATION_NAME AS TABLENAME');
SysIB.SQL.Add( 'from RDB$RELATION_FIELDS RR join RDB$VIEW_RELATIONS RV on RR.RDB$VIEW_CONTEXT=RV.RDB$VIEW_CONTEXT and RR.RDB$RELATION_NAME=RV.RDB$VIEW_NAME');
SysIB.SQL.Add( 'where ( (RDB$RELATION_FIELDS.RDB$RELATION_NAME=:CURRENTNAM E');
.
.
.
end;
</pre>
Anschliessend kann deinen Funktion wie folgt aussehen:
<pre>
procedure GetIBFields( const FieldNames, TableNames: TStrings; const sTableName );
begin
FieldNames.Clear;
TableNames.Clear;
Try
SysIB.Close;
SysIB.Params[0].AsString := sTableName;
SysIB.ExecQuery;
while not SysIB.eof do
Begin
FieldNames.Add( Trim( SysIB.FieldByName('FIELDNAME').AsString ) );
TableNames.Add( Trim( SysIB.FieldByName('TABLENAME').AsString ) );
SysIB.next;
end;
except
end;
end;
</pre>
Wenn Du eine SQL-Abfrage dynamisch erzeugst die auch joins enthält, dann musst Du bei der Generierung der Abfrage parallel dazu für jede beteiligte Tabelle/View die Funktion ausführen um an die gewünschten Informationen zu kommen.
Gruß
Gesin
Comment
Comment