Announcement

Collapse
No announcement yet.

ADO & DataType Number bzw numeric

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

  • ADO & DataType Number bzw numeric

    Hallo,

    ich habe folgendes Problem. Wenn ich Daten aus einer Oracle DB bzw MSSQL auslese gibt es normal beim darstellen in einen DBGrid keine Schwierigkeiten.
    Wird aber in Oracle der Datentyp number benutzt mit eine size=16 oder in MSSQL den Datentyp numeric dann kommt es zum Überlauf wenn die Dezimalstellen der Zahl > 15 ist. Bei diesen Typen benutzt ADO den Delphityp TBCDField wenn die Eigenschaft 'EnableBCD' des jeweiligen AdoDataSets 'true' ist. Ergebnis es wird ein 'Overflow' im DBGrid angezeigt. Ist die Eigenschaft auf false gesetzt benutzt ADO den Typ TFloatField welcher natürlich bei grossen Zahlen ein Potenz anzeigt.
    In der Hilfe steht man solle den Typ TVariantField bei großen Zahlen nutzen. Ist auch ok aber wie soll ich diesen einstellen bzw zuweisen wenn
    die Eigenschaft 'EnableBCD' ein Boolean-wert ist?
    Da meist unbekannte SQL-Statements benutzt werden kann ich die readonly-Eigenschaft auch nicht zur Laufzeit ändern.
    HAt jemand einen Rat?
    Danke.

  • #2
    Hallo,

    >..benutzt ADO den Delphityp TBCDField ..

    nicht ADO (COM-Objekte von Microsoft) nutzt TBCDField, sondern die VCL-Umverpackung ADO Express. Wenn man nur mit den nativen ADO-Objekten (Connection + Recordset) arbeitet, treten diese Probleme nicht auf.

    Mit welcher Delphi-Version wird gearbeitet? Borland hat in der Vergangheit verschiedene inoffizielle Sourcecode-Patches für die VCL verteilt, die derartige Darstellungsprobleme teilweise korrigieren

    Comment


    • #3
      Hallo Herr Kosch,
      <br><br>genutzt wird Delphi6 D ohne SP. Eingesetzt habe ich die Module TADOConnection,TADOTable und TADOQuery. Die Typenzuordnung wird in der Funktion ADOTypeTOFieldType in ADODB.dcu(pas) durchgeführt.
      <br> Wäre es möglich dort den Typ ftVariant statt ftFloat als Ergebnis zu übergeben? - Wenn EnableBCD = false ist - Ohne Datenverlust?
      <br><br><u>Danke</u&gt

      Comment


      • #4
        Hallo,

        die ADO Express-Komponenten TADOTable und TADOQuery sollten <b>niemals</b> verwendet werden - diese Dinger dienen nur dem Marketing ("... eine BDE-Anwendung einfach auf ADO umstellen..."). Statt dessen ist <b>TADODataSet</b> und <b>TADOCommand</b> der richtige Weg.

        Das folgende Beispiel demonstriert einen Workaround. Über die Interface-Methode <b>Collect</b> des nativen Recordset-Objekts kann der Wert direkt ausgelesen werden. Den Interface-Zeiger kann man auf verschiedenen Wegen abfordern:<br>
        a) Direkter Zugriff auf das Recordset-Objekt, oder <br>
        b) von TADODataSet über die Eigenschaft Recordset abfordern
        <pre>
        { ************************************************** **************
        Autor : Andreas Kosch
        Compiler : Delphi 6.0 Enterprise
        Betriebssystem : Windows 2000 SP2
        Erstellt am : 21.11.2001
        Beschreibung : TLargeintField-Bug von ADO Express

        USE tempdb
        GO
        CREATE TABLE BigIntTest (
        TLB_ID INT NOT NULL IDENTITY PRIMARY KEY,
        Wert BIGINT NOT NULL)
        GO
        INSERT INTO BigIntTest (Wert) VALUES (1)
        INSERT INTO BigIntTest (Wert) VALUES (0)
        INSERT INTO BigIntTest (Wert) VALUES (-1)
        GO
        SELECT * FROM BigIntTest

        Fall 1: Zugriff über die nativen ADO-Objekte (Recordset mit implizitern Connection-Objektinstanz):
        Ergebnis:
        1
        0
        -1

        Fall 2: TADOConnection + TADODataSet
        Ergebnis im TDBGrid:
        1
        0
        1

        ************************************************** ************** }

        unit BIGINT_Bug_Delphi6DemoFrm;

        interface

        uses
        Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
        Dialogs, ExtCtrls, DBCtrls, Grids, DBGrids, DB, ADODB, ComCtrls, StdCtrls;

        type
        TForm1 = class(TForm)
        ADOConnection1: TADOConnection;
        ADODataSet1: TADODataSet;
        ADODataSet1TLB_ID: TAutoIncField;
        ADODataSet1Wert: TLargeintField;
        DataSource1: TDataSource;
        DBGrid1: TDBGrid;
        DBNavigator1: TDBNavigator;
        StatusBar1: TStatusBar;
        ButtonNativeADO: TButton;
        ButtonWorkaround: TButton;
        procedure ButtonNativeADOClick(Sender: TObject);
        procedure ButtonWorkaroundClick(Sender: TObject);
        private
        { Private-Deklarationen }
        public
        { Public-Deklarationen }
        end;

        var
        Form1: TForm1;

        implementation

        {$R *.dfm}

        uses ADOInt, Variants;

        procedure TForm1.ButtonNativeADOClick(Sender: TObject);
        resourcestring
        cCS = 'Provider=SQLOLEDB.1;Persist Security Info=False;' +
        'User ID=sa;Initial Catalog=tempdb;Data Source=ITERFT01T006;';
        var
        aRS : _Recordset;
        begin
        aRS := CoRecordSet.Create;
        aRS.CursorLocation := adUseClient;
        try
        aRS.Open('select TLB_ID, Wert from dbo.BigIntTest', cCS,
        adOpenStatic, adLockReadOnly, adCmdText);
        aRS.MoveFirst;
        while not aRS.EOF do
        begin
        ShowMessage('Ergebnis: ' + VarToStr(aRS.Collect[1]));
        aRS.MoveNext;
        end;
        finally
        aRS.Close;
        end;
        end;

        procedure TForm1.ButtonWorkaroundClick(Sender: TObject);
        var
        aRS : _Recordset;
        s64 : String;
        i64 : Int64;
        begin
        aRS := ADODataSet1.Recordset;
        aRS.MoveFirst;
        while not aRS.Eof do
        begin
        s64 := aRS.Collect[1];
        i64 := StrToInt64(s64);
        ShowMessage(IntToStr(i64));
        aRS.MoveNext;
        end;
        end;

        end.
        </pre&gt

        Comment


        • #5
          Hallo,
          <br><br><b>Vielen Dank</b> für Ihre Info's.
          <br>In meinen Projekt verschwinden nun nach und nach TADOTable und TADOQuery. Man sollte nicht immer den bequemsten Weg gehen.
          <br>Zu Testzwecken habe ich in der Tat ADDB.pas angepasst und den Typ ftVariant statt ftFloat als Ergebnis übergeben wenn EnableBCD = false ist. Für eine readonly DBGrid ausreichend aber nicht Sinn der Sache.
          <br>Ergo: Ich werde jetzt sofort Ihr Buch <b>Ado und Delphi</b> bestellen.
          <br><b><i>Frohe Ostern</i></b&gt

          Comment


          • #6
            Hallo,

            &gt;Ergo: Ich werde jetzt sofort Ihr Buch Ado und Delphi bestellen.

            das ist eine sehr gute Idee :-)

            Zumal das Buch in dieser Woche aus der Druckerei kommt und somit auch tatsächlich verfügbar ist

            Comment


            • #7
              Hallo Herr Kosch,
              <br><br>
              <pre>
              ...
              USE tempdb
              GO
              CREATE TABLE BigIntTest (
              TLB_ID INT NOT NULL IDENTITY PRIMARY KEY,
              Wert BIGINT NOT NULL)
              GO
              INSERT INTO BigIntTest (Wert) VALUES (1)
              INSERT INTO BigIntTest (Wert) VALUES (0)
              INSERT INTO BigIntTest (Wert) VALUES (-1)
              GO
              SELECT * FROM BigIntTest
              ...
              </pre>
              <br>Haben Sie den Test mit einen grossen Wert durchgeführt?
              <br>Z.B. <b>12345678901234567</b>.
              <br>Da auch hier <i>ADODB</i> benutzt wird wird es auch zum Overflow kommen.
              <br><br>
              mfg Bern

              Comment


              • #8
                Hallo,

                &gt;Haben Sie den Test mit einen grossen Wert durchgeführt? <br>
                &gt; z.B. 12345678901234567.

                positive Zahlen sind nicht das Problem, der Wert 12345678901234567 wird sowohl von TADODataSet als auch von den nativen ADO-Objekten korrekt angezeigt.

                P.S: Der Bug mit den negativen BIGINTs wird selbstverständlich vom offiziellen UpdatePack#2 für Delphi 6 <b>nicht</b> korrigiert :-

                Comment

                Working...
                X