Announcement

Collapse
No announcement yet.

TIBSQL und Fieldcount

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • TIBSQL und Fieldcount

    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

  • #2
    Hallo,

    welche Delphi-Version wird verwendet? Wenn es sich um Delphi 6 handelt, schlägt <b>TIBClientDataSet</b> gleich 2 Fliegen mit einer Klappe, da TIBSQL und TStringList überflüssig werden

    Comment


    • #3
      Hallo Herr Kosch,<p>es handelt es um Delphi 5 SP1, IBX 4.63. ClientDataSet verwende ich nich, da ich da noch eine DLL mitausliefern muß. Ich habe mir eine Komponente gebaut die die Daten in ein TRxMemoryData-Object (RXLib 2.75) einliest. Funktioniert genauso gut.<p>Gruß, Andreas Brüc

      Comment


      • #4
        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


        • #5
          Hallo Gesine,<p>danke für die Funktion. Die SQL-Abfrage ändert sich aber immer zu laufzeit und enthält joins. Gibt es da auch ne Möglichkeit?<p>Gruss Andrea

          Comment


          • #6
            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


            • #7
              Hallo zusammen,

              die Antwort kommt vielleicht etwas spät, aber ich glaube ich habe eine ziemlich einfache Lösung gefunden:
              ich zähle mit der JCL-Funktion StrStrCount einfach die Kommas im SQL-Statement und erhalte so die Anzahl der Felder in dem IBSQL-Recordset.

              Gruß
              Uw

              Comment

              Working...
              X