Announcement

Collapse
No announcement yet.

Interbase: Problem nach Sortierung gem. Index

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

  • Interbase: Problem nach Sortierung gem. Index

    Hallo,

    Konfig.:
    - Delphi 5 Update Pack 1<br>
    - Interbase 6.01 Open Source<br>
    - BDE 5.2.0.2<br>
    - Zugriff auf die IB-Datenbank erfolgt via TTable/TQuery und nicht über IBX<br>

    SQL-Script-Fragment für Datenbankerzeugung:

    <pre>
    SET SQL DIALECT 3;

    /* Datenbank erzeugen */
    CREATE DATABASE '<MyDBFile>.gdb'
    USER '<MyUser> PASSWORD '<MyPassword>';

    /* Domains der Datenbank festlegen */
    CREATE DOMAIN TID AS INTEGER;
    CREATE DOMAIN TDescription AS VARCHAR(250);
    CREATE DOMAIN TInfo AS VARCAHR(255);

    /* Tabellen erzeugen */
    CREATE TABLE MyTable (
    ID TID NOT NULL,
    Beschreibung TDescription NOT NULL,
    Zusatzinformation TInfo
    );
    ALTER TABLE MyTable
    ADD CONSTRAINT PK_MyTable PRIMARY KEY(ID);
    CREATE UNIQUE ASCENDING INDEX IDX_MyTable ON MyTable(Beschreibung);
    COMMIT WORK;
    </pre>

    In der Anwendung hat man die Möglichkeit nach der Beschreibung (auf der ein Index <i>lastet</i>) zu sortieren. Die Sortierung erfolgt über

    <pre>
    with TMyTable do begin
    Close;
    try
    IndexName := ’IDX_MyTable’;
    finally
    Open;
    end;
    end;
    </pre>

    Dies funktioniert alles tadellos.

    Liegt die sortierte Reihenfolge vor, so bekommt man, für den Fall, dass man in den Edit-Mode schaltet, bei einigen (wenigen) Datensätzen die Fehlermeldung <b>"Datensatz/Schlüssel gelöscht"</b>. Eine Bearbeitung des aktuellen Datensatzes ist somit nicht möglich. Hebe ich die Sortierreihenfolge auf (es wird nach dem Primärschlüssel sortiert), lokalisiere genau den Datensatz, der vorher diesen (komischen und seltsamen) Fehler nach sich gezogen hat, so klappt jetzt alles wunderbar. Man kann den Datensatz bearbeiten. Sortiert man wieder und versucht zu bearbeiten...Fehler. In den <i>ominösen</i> Datensätzen sind keine besonderen Zeichen (Umlaute, o.ä) vorhanden.

    Bei anderen Datenbanken (Paradox, MS SQL 2000) läuft alles wunderbar.

    Ein Problem mit Interbase 6.01 in Bezug auf Indizes?

    Danke im voraus<br>
    Stephan

  • #2
    Hallo,

    nein - am InterBase liegt das nicht. Was protokolliert der <b>SQL-Monitor</b> im Fehlerfall mit. Bei mir sieht das so aus (ich habe die Testdatenbank erzeugt und mit einigen Testdatensätzen gefüllt, kann das Problem jedoch nicht reproduzieren):
    <pre>
    a) SQL Execute: INTRBASE - SELECT "ID" ,"BESCHREIBUNG" ,"ZUSATZINFORMATION" FROM "MYTABLE" ORDER BY "BESCHREIBUNG" ASC
    ...
    b) SQL Execute: INTRBASE - SELECT "ID" ,"BESCHREIBUNG" ,"ZUSATZINFORMATION" FROM "MYTABLE" WHERE "BESCHREIBUNG"=?
    ...
    c) SQL Execute: INTRBASE - UPDATE "MYTABLE" SET "ZUSATZINFORMATION"=? WHERE "ID"=? AND "BESCHREIBUNG"=? AND "ZUSATZINFORMATION"=?
    </pre>

    Fall a) Index wird zur Sortierung aktiviert <br>
    Fall b) Datensatz wird in den Editiermodus geschaltet <br>
    Fall c) Datensatz wird nach dem Editieren gepostet

    Testprogramm:
    <pre>
    object Form1: TForm1
    Left = 317
    Top = 114
    Width = 696
    Height = 480
    Caption = 'Form1'
    Color = clBtnFace
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -11
    Font.Name = 'MS Sans Serif'
    Font.Style = []
    OldCreateOrder = False
    PixelsPerInch = 96
    TextHeight = 13
    object DBGrid1: TDBGrid
    Left = 16
    Top = 80
    Width = 345
    Height = 120
    DataSource = DataSource1
    TabOrder = 0
    TitleFont.Charset = DEFAULT_CHARSET
    TitleFont.Color = clWindowText
    TitleFont.Height = -11
    TitleFont.Name = 'MS Sans Serif'
    TitleFont.Style = []
    end
    object DBNavigator1: TDBNavigator
    Left = 16
    Top = 56
    Width = 340
    Height = 25
    DataSource = DataSource1
    TabOrder = 1
    end
    object Button1: TButton
    Left = 136
    Top = 16
    Width = 75
    Height = 25
    Caption = 'Button1'
    TabOrder = 2
    OnClick = Button1Click
    end
    object Database1: TDatabase
    Connected = True
    DatabaseName = '_Schneider'
    DriverName = 'INTRBASE'
    LoginPrompt = False
    Params.Strings = (
    'SERVER NAME=C:\Database\SSCHNEIDER.GDB'
    'USER NAME=SYSDBA'
    'OPEN MODE=READ/WRITE'
    'SCHEMA CACHE SIZE=8'
    'PASSWORD=masterkey')
    SessionName = 'Default'
    Left = 16
    Top = 16
    end
    object Table1: TTable
    Active = True
    DatabaseName = '_Schneider'
    TableName = 'MYTABLE'
    Left = 56
    Top = 16
    object Table1ID: TIntegerField
    FieldName = 'ID'
    Required = True
    end
    object Table1BESCHREIBUNG: TStringField
    DisplayWidth = 10
    FieldName = 'BESCHREIBUNG'
    Required = True
    Size = 250
    end
    object Table1ZUSATZINFORMATION: TStringField
    DisplayWidth = 10
    FieldName = 'ZUSATZINFORMATION'
    Size = 255
    end
    end
    object DataSource1: TDataSource
    DataSet = Table1
    Left = 88
    Top = 16
    end
    end
    </pre>
    &#10

    Comment


    • #3
      Hallo Herr Kosch,

      danke für Ihre Bemühungen.

      Das Protokoll des SQL-Monitors sehe ich mir noch an und gebe dann Bescheid. Was mir noch aufgefallen ist (beim Debuggen) ist folgendes:

      Vorab: Wenn bei einem Datensatz im DBGrid ein Doppelklick gemacht wird, wird ein "Bearbeitungsformular" aufgerufen (analog den edXXXX.pas/dfm-Dateien des Borland-MastApp-Bespiels). Hier steht in der <i>Edit(No: Integer)-Methode</i> dieser Forms (und auch meiner Forms):<br>
      MyTable.Open;<br>
      MyTable.Locate('ID', No, []);<br>
      ShowModal;<br>

      Genau beim Locate() machts "bumm". Klammere ich das Locate() aus, öffnet sich zwar das Form, der korrekte Text der Felder wird angezeigt, aber der Versuch den Text in einem DBEdit-Feld zu bearbeiten führt zum Fehler: "Datensatz/Schlüssel gelöscht"

      Und genau hier steht ja keine einzige eigene Programmzeile.
      Zum Posten kommt man gar nicht.

      Gruß<br>
      Stepha

      Comment


      • #4
        Hallo,

        bei einer Client/Server-Datenbank arbeitet jedes Programm immer nur mit einer <b>Kopie</b> der Daten, die als Ergebnismenge vom SQL-Server abgerufen wurde. Wenn Delphi in den Edit-Modus schaltet, versucht die VCL, die aktuellste Version des zu bearbeitenden Datensatzes neu vom Interbase abzufordern, wobei ein WHERE-Kriterium diesen Datensatz aus der Datenmenge logisch eindeutig kennzeichnen muss. Wenn der InterBase keinen Datensatz findet, der zu diesem WHERE-Kriterium passt, löst Delphi die Exception "Datensatz/Schlüssel gelöscht" aus. Was passiert, wenn alle TTable-Instanzen für die Eigenschaft <b>UpdateMode</b> den Wert <b>upWhereKeyOnly</b> verwenden?

        Ohne die exakten Protokolle des SQL-Monitors ist eine Suche nach der Ursache für dieses Problem nicht möglich

        Comment


        • #5
          Hallo Herr Kosch,

          ich habe Ihnen das Protokoll des SQL-Monitors geschickt.

          Auch bei TTable.UpdateMode = upWhereKeyOnly leider das gleiche, fehlerhafte Verhalten. Sobald es in den Edit-Mode geht..."Datensatz/Schlüssel gelöscht".

          Stepha

          Comment


          • #6
            Hallo,

            in der Protokolldatei des SQLMonitors ist nicht zu erkennen, worin die Ursache für dieses Problem liegen sollte. Die Suche nach dem Primärschlüsselwert 1334 (ID) sollte beim InterBase immer einen Datensatz zurückliefern, sofert dieser Datensatz nicht in einer späteren Transaktion als der eigenen Lese-Transaktion angelegt wurde.
            <pre>
            488 12:37:28 SQL Data In: INTRBASE - Param = 1, Name = ID, Type = fldINT32, Precision = 1, Scale = 0, Data = 1334
            489 12:37:28 SQL Execute: INTRBASE - SELECT ID ,BESCHREIBUNG ,ZUSATZINFORMATION FROM AUSPRAEGUNG WHERE ID=?
            </pre&gt

            Comment


            • #7
              Hallo Herr Kosch,

              zuerst einmal vielen herzlichen Dank für Ihre Bemühungen.

              Was bedeutet das konkret bzw. was kann ich tun, um den "Fehler" zu lokalisieren. Wie bereits gesagt, es passiert eigentlich nichts Außergewöhnliches:

              BDE 5.2, INTRBASE-Treiber mit 6.01-GDB-File, die Daten werden im Grid angezeigt, und sobald Edit-Mode…boom. Keine einzige eigene Programmzeile an dieser Stelle!

              Im Datenmodul:<br>
              <pre>
              <b>object</b> Database1: TDatabase
              AliasName = 'MyDBAlias'
              DatabaseName = 'DB1'
              LoginPrompt = False
              SessionName = 'Default'
              TransIsolation = tiDirtyRead
              Left = 16
              Top = 16
              <b>end</b>
              <b>object</b> Ausp: TTable
              BeforePost = AuspBeforePost
              BeforeDelete = AuspBeforeDelete
              OnDeleteError = AuspDeleteError
              OnNewRecord = AuspNewRecord
              OnPostError = AuspPostError
              DatabaseName = 'DB1'
              TableName = 'Auspraegung'
              Left = 176
              Top = 64
              <b>object</b> AuspID: TIntegerField
              FieldName = 'ID'
              Required = True
              <b>end</b>
              <b>object</b> AuspBeschreibung: TStringField
              DisplayWidth = 250
              FieldName = 'Beschreibung'
              Required = True
              Size = 250
              <b>end</b>
              <b>object</b> AuspZusatzinformation: TStringField
              FieldName = 'Zusatzinformation'
              Size = 255
              <b>end</b>
              <b>end</b>
              </pre>

              Die Datenbank selbst wurde von einer vorherigen Version auf die neue Version migriert, die Anwendung (in der es diesen Fehler hagelt) arbeitet somit gleich mit einer "befüllten" Datenbank. Die Datenbanktabellen werden im Rahmen einer eigenen Anwendung migriert. Die Migration selbst kopiert die Daten von einer Quell-Datenbank in die neue Ziel-Datenbank.

              Gruß<br>
              Stepha

              Comment


              • #8
                Hallo <br> auffällig finde ich die länge von varchar(250) für diesen Index
                ich hatte schon bei varchar(129) probleme mit Dialect

                Comment


                • #9
                  Hallo,

                  danke für die Antwort.

                  Leider <b>müssen</b> die Beschreibungsfelder, auf denen ein Index lastet, eine Größe von 250 haben.

                  Hattest Du das gleiche Problem mit <i>Datensatz/Schlüssel gelöscht</i>?<br>
                  Wenn ja, wie hast Du das Problem gelöst?

                  Mein Fehler taucht sowohl bei Dialect 1 und Dialect 3 Datenbanken auf, sowohl auf dem IB-Server 5.5 als auch bei 6.01. Der einzige Unterschied zu vorherigen Releases der Anwendung (und da tauchte der Fehler sicher nicht auf) war der, das diese mit Delphi 3 C/S compiliert wurde.

                  Stepha

                  Comment


                  • #10
                    Soweit ich weis ist bei varchar(253)die max. Länge erreicht.<br>
                    Ich habe eine Prüfsumme verwendet um zu indizieren.<br>
                    Warum benötigst du den einen Index auf das Feld ?<br>
                    Andrea

                    Comment


                    • #11
                      Hallo Andreas,

                      danke für den Tipp mit der Maximallänge von 253. Muss ich noch nachvollziehen, um ggf. die Länge dieses Attributes zu ändern.

                      Ein Index ist aus Gründen der Datenintegrität (hier: Forderung nach eindeutigen Werten) nötig. Darüber erleichert er die Suche in den Datenbeständen (die sind aus Historisierungsgründen sehr angewachsen)

                      Gibt es eine Art Richtgröße für die Maximallänge für einen Index auf einem VARCHAR()-Feld, so dass die Implementierung nicht nur bei Interbase, sondern auch bei Oracle, MS SQL, usw. problemlos funktioniert?

                      Stepha

                      Comment


                      • #12
                        Sorry, noch eine Anmerkung: Das betroffene Feld Beschreibung hat nur(!) eine Länge von 250 (somit < 253). Ein Zeichensatz ist auch nicht explizit angegeben

                        Stepha

                        Comment


                        • #13
                          Hi,

                          habe es gerade mit einer Größe von 200 getestet.
                          Gleiches Problem... :-(

                          Stepha

                          Comment


                          • #14
                            Jetzt mische ich mich doch mal ein:

                            Ist es notwendig mit TTable zu arbeiten, schon TIBXTable ist ein Schmarn, aber mit einer TTable auf einen SQL-Server sollte man einfach nicht tun. Die BDE macht dann lauter Dinge, die der SQL-Server besser kann, und anscheinend verurachst sie dann auch unnötige Probleme.

                            p.s. Ich schreibe SQL-Server und nicht InterBase, weil das für alle SQLServer gilt (Oracle, InterBase, MSSQL, ...

                            Comment


                            • #15
                              Hi Andreas

                              mische Dich ruhig ein :-)

                              Das Problem ist, das diese Anwendung sowohl Desktop-DBs (Paradox) als auch SQL-Server unterstützen <b>muss</b>. Das heist, der kleinste gemeinsame Nenner ist angesagt, und das ist schon bitter genug.

                              Es gab schon solche Diskussionen hier (fand ich sehr gut), davon abzukommen eine Anwendung zu schreiben, die eben allen Ansprüchen genügt (Desktop, RDBMS). Besser ist es, sich auf SQL-Server zu konzentrieren und soweit wie möglich alles auf den Server (Stichwort: Stored Procedures und Konsorten) auszulagern. Somit wahrt man Unabhängigkeit, die man bei der Unterstützung mit Desktop-DBS nie haben kann, da hier leider nur das FAT-Client-Prinzip zum Tragen kommen kann. Aber FAT-Server ist das Ziel...

                              Gruß<br>
                              Stepha

                              Comment

                              Working...
                              X