Neuigkeiten:

Wenn ihr euch für eine gute Antwort bedanken möchtet, im entsprechenden Posting einfach den Knopf "sag Danke" drücken!

Mobiles Hauptmenü

aus 7,35 wird 7.34999999999999960e+000 und Datensatz wird nicht mehr gefunden

Begonnen von Java-Jim, Januar 31, 2013, 19:19:27

⏪ vorheriges - nächstes ⏩

Java-Jim

Ich arbeite derzeit an einer Access 2010 Datenbank als Frontend, die über den MySQL ODBC 5.1 Treiber auf verknüpfte Tabellen eines MySQL Server 4.1 zugreift.
Es gibt dort ein Formular mit verknüpftem Unterformular. Auf dem Formular wird aus Rüstzeit und Verrechnungssatz die Rüstkosten berechnet und in ein Feld gespeichert.

Unter gewissen Umständen wirft Access beim UPDATE die Fehlermeldungen
Fehler Nr. 3197 Access-Datenbankmodul hat den Vorgang angehalten, da Sie und ein weiterer Benutzer gleichzeitig versuchen, dieselben Daten zu ändern.
Sowie Schreibkonflikt - In Zwischenablage kopieren oder Eigene Änderungen verwerfen.
Sowie Fehler Nr. 3021 Kein aktueller Datensatz.

Ich habe recherchiert und die typischen Fehlerursachen kein Timestamp-Feld oder kein Primärschlüssel ausgeschlossen.
Ich habe auch me.dirty=false und me.requery im Formular/UFO eingepflegt um sicherzustellen, dass die geänderten Daten geschrieben werden und das Formular die Datenquelle aktualisiert.
Ich habe auch sichergestellt, dass der Datenbankserver nicht seinerseits die Daten beim Speichern ändert, beispielsweise wenn der Wert größer als der Wertebrereich wäre.

Dann habe ich die Protokollierung im ODBC-Treiber aktiviert und herausgefunden, dass die Fehlermeldung mich in die Irre geführt hat !

Es hat nämlich nichts damit zu tun, dass die Daten auf irgendeine Weise verändert wurden, sondern das der betreffende Datensatz gar nicht erst wiedergefunden werden kann.

Im myodbc.sql konnte ich sehen, was das gebundene Formular beim Aktualisieren macht:
Da erscheint der Fehler...
UPDATE `tblarbeitsplanpositionen` SET `Beschreibung`='test1'  WHERE `Aplanpos-ID` = 78018 AND `Aplan-Id` = 20020 AND `Nr` = 1 AND `KST` = 200 AND `KR` = 7.34999999999999960e+000 AND `KB` = 5.77500000000000040e+000 AND `TR` = 1.20000000000000000e+001 AND `TE` = 1.00000000000000000e+001 AND `Lastupdate` = _binary'2013-01-31 13:33:11';
ROLLBACK;


Da erscheint kein Fehler...
UPDATE `tblarbeitsplanpositionen` SET `Beschreibung`='test1'  WHERE `Aplanpos-ID` = 78043 AND `Aplan-Id` = 20020 AND `Nr` = 2 AND `KST` = 210 AND `KR` = 1.30900000000000000e+001 AND `KB` = 1.39408500000000000e+003 AND `TR` = 2.20000000000000000e+001 AND `TE` = 2.34300000000000000e+003 AND `Lastupdate` = _binary'2013-01-31 13:24:55';
COMMIT;



Auf dem Formular steht KR=7,35 im Datensatz steht KR=7,35000. Nur Access macht daraus automatisch KR=7.34999999999999960e+000.
(Der Datentyp ist im übrigen ein DOUBLE mit Lenght/Set=15,5.)
Das führt dazu, dass die WHERE Klausel kein Ergebnis findet und das UPDATE nicht erfolgen kann. Access meckert dann und denkt, ein anderer hätte den angezeigten/zu ändernden Datensatz verändert.

Zum Test habe im SQL Statement von Hand den Wert auf 7.350e+000 geändert. Somit erfolgt das UPDATE ohne Fehler, sonst heißt es 0 rows found, 0 rows affected.

Damit scheint die Ursache schon ein mal gefunden.
Da das Formular aber gebunden ist und die UPDATE Statements von sich aus generiert, kann ich auf das Format der Zahlendarstellung nicht einwirken. Man könnte natürlich das SQL Statement im VBCode korrekt erzeugen und ausführen lassen, aber eigentlich habe ich keine Lust dazu.
Ich hatte in Erwägung gezogen den Datentyp von DOUBLE in DECIMAL zu ändern, bin mir aber über die Konsequenzen nicht ganz im klaren. Da es um Währungsbeträge geht, bin ich beim Runden der Nachkommastellen etwas skeptisch.



1. Ist es normal, dass Access in Verbindung mit Fließkommazahlen die Werte in Exponentialschreibweise angibt?
2. Wieso kann Access den Wert 7,35000 in die Tabelle speichern und verwendet beim Update dann 7.34999999999999960e+000 als Kriterium? Ist doch immer das gleiche Prozedere...
3. Kann ich bedenkenlos den Datentypwechsel bei einer große Tabelle durchführen oder muss ich dann damit rechnen, dass die Kosten durch Rundung sich wesentlich verändern?

Hat vielleicht von euchen einen guten Rat wie das Problem zu lösen ist?

Grüße
Java-Jim

DF6GL

Hallo,

ich denke, dass ein Umstieg auf Currency  (Festkommazahl, 4 Dezimalstellen Genauigkeit) keine Probleme hervorrufen würde.  


Nachdem Double ein Gleitkomma-Datentyp ist und intern mittels Logarithmen und dazu noch binär (wer hätte das gedacht  ;-) ) verrechnet wird, wird es immer irgendwelche Ungenauigkeiten im Bereich ,bzw. nach der letzten gültigen Stelle geben, die bei der Konvertierung  auf andere Darstellungsmethoden eben zu diesen Effekten führen.  Genau wegen dieses Verhaltens sollte man Double-Werte nicht genau ( mit z. B: "=" ) , sondern in einen gewissen Toleranzbereich (mit "<" und ">" ) vergleichen.  

Andererseits verstehe ich nicht die Notwendigkeit, in der Where-Condition mit solchen Zahlen zu jonglieren...  

Wurliwurm

Währungsbeträge gehören immer als Ganzzahl in der Datenbank gespeichert. Andernfalls sind Probleme der beschriebenen Art vorprogrammiertert. Inbesondere bei unterschiedlichen Plattformen.