![]() |
Datenbank: Oracle • Version: 10g • Zugriff über: Bdp
Fließkommazahlen Delphi vs. Oracle
Hallo,
ich habe ein Problem mit dem Decimalseparator. Ich möchte über eine Delphi-Anwendung Fließkommazahlen in einer Oracle-Datenbank speichern. Oracle erwartet einen '.' als Trennzeichen, während Delphi das ',' benutzt. Ich habe die NLS_NUMERIC_CHARACTERS umgestellt, so dass ein Speichern möglich ist. Die Zahlen werden auch richtig in der Datenbank abgelegt! Lese ich nun aber mit meiner Anwendung die Tabelle wieder aus, wird das Trennzeichen einfach überlesen und ich habe anstatt 7.45 nun 745. Kann mir jemand einen Tip geben, wie man am besten mit Fließkommazahlen umgeht? |
Re: Fließkommazahlen Delphi vs. Oracle
Zitat:
so ganz richtig ist das nicht. Eigentlich zeigt das aus schon, dass Du auf den National Language Support zurückgreifst. An sich benutzen sowohl Delphi als auch Oracle einfach lokalisierte Einstellungen. Delphi greift dabei immer auf die Einstellungen unter Windows zurück. I.d.R. wirst Du in Deutschland Rechner mit deutscher Lokalisierung finden und hier ist eben das Komma der Dezimalseperator. Wichtig ist, dass Du Dich eigentlich nie auf diesen verlassen solltest. Das man selbst einen solchen Rechner verwendet heißt natürlich nicht, dass alle Rechner auf denen das Programm einmal läuft ebenfalls diesen Dezimalseperator verwenden. So kann ein Kunde durchaus einen englisch lokalisierten haben, der erwartet dann den Dezimalpunkt (und natürlich kommen noch ganz andere Dinge in Frage). Deshalb greift man häufig auf eine einheitliche Lokalisierung zurück, damit eine Datei auf einem dt. Rechner gespeichert und problemfrei auf einem eng. geladen werden kann und vice versa. Dafür gibt es spezielle Strukturen, die Informationen über die bei einer Konvertierung zu verwendenden Einstellungen enthalten. Unter Delphi.Win32 währen das TFormatSettings, unter .net findest Du Implementierungen des IFormatProvider-Interface. In Deinem Fall die Klasse NumberFormatInfo und hier die Eigenschaft numberDecimalSeperator. Erzeuge hier eine neue Instanz, setz den Dezimalseperator und übergib diese Instanz dann an die toString Methode als zweites Argument (erstes ist weiterhin die zu konvertierende Zahl). Gruß Der Unwissende |
Re: Fließkommazahlen Delphi vs. Oracle
Hi,
danke erstmal für deine Antwort! Problem ist, ich benutze keine toString-Methode. Ich lese die Datenbank aus und fülle den Inhalt in ein Datagrid bzw. DataSet und dort verschwindet das Komma dann einfach. Beim Speichern habe ich das Problem, dass wenn ich die NLS-Einstellungen nicht vornehme jedesmal ein Fehler auftritt, wenn ich meinen Datenkomponenten einen Floatwert zuweise
Delphi-Quellcode:
Wenn ich den Parametern beispielsweise einfach einen String zuweise wie 7.45, '7.45', oder aber auch 7,45, wird das nicht akzeptiert, da es nicht als Floatwert erkannt wird...with BdpUpdate2, Datensatz do begin if Connection.State = System.Data.ConnectionState.Closed then Connection.Open; Parameters.Item[0].Value := fConvertStrToDouble(VS,2); Parameters.Item[1].Value := U1ERST1; if U1SATZ1 <> '' then Parameters.Item[2].Value := fConvertStrToDouble(U1SATZ1,2); Parameters.Item[3].Value := U1ERST2; if U1SATZ2 <> '' then Parameters.Item[4].Value := fConvertStrToDouble(U1SATZ2,2); Parameters.Item[5].Value := U1ERST3; if U1SATZ3 <> '' then Parameters.Item[6].Value := fConvertStrToDouble(U1SATZ3,2); Parameters.Item[7].Value := U1ERST4; if U1SATZ4 <> '' then Parameters.Item[8].Value := fConvertStrToDouble(U1SATZ4,2); Parameters.Item[9].Value := U1ERST5; ... end; |
Re: Fließkommazahlen Delphi vs. Oracle
Zitat:
Zitat:
|
Re: Fließkommazahlen Delphi vs. Oracle
Zitat:
Delphi-Quellcode:
Beschreibe nochmal kurz, was ich überhaupt machen will. Also ich lese eine Txt-Datei ein, in der Datensätze gespeichert sind. Es geht halt darum diese Datensätze nun in der Datenbank zu speichern. In der Txt-Datei sind die Fließkommazahlen mit einem ',' gespeichert.
{_______________________________________________________________________________
Wandelt einen String in eine Floatzahl um @param Fstring (in) : String, der umgewandelt werden soll @param decimals (in) : Anzahl der Nachkommastellen @return (out) : 0 --> Zahl konnte nicht umgewandelt werden sonst --> umgewandelte Float-Zahl _______________________________________________________________________________} function fConvertStrToDouble(Fstring : string ; decimals : integer):double; var i : byte; temp : double; settings : TFormatSettings; begin Result := 0; kommaCount := 0; //englischen Zahlen-Standard laden (Decimalseperator = '.') GetLocaleFormatSettings(1033, settings); for i := 1 to Length(Fstring) do if Fstring[i] = ',' then begin fString[i] := '.'; end; //String umwandeln if TryStrToFloat(Fstring,temp,settings) then Result := temp; end; Ich lese also die Zahl mit dem Komma als String ein und will es dann in der fConvertStrToDouble umwandeln. Wie du siehst habe ich da auch schonmal mit den TFormatSettings gearbeitet. (Ist das überhaupt .Net-Kompatibel?) Wie gesagt, bisher sind bei mir alle Versuche mit dem Komma als Separator zu arbeiten, fehlgeschlagen. |
Re: Fließkommazahlen Delphi vs. Oracle
Warum musst du überhaupt umwandeln? DAS ist der große Fehler. ;-)
Dem Oracle client ist es schnurz-piepe was die Regionaleinstellungen des Users im Betriebssystems sind. Steht in der Registry AMERICA_AMERICAN, dann wird er das nehmen. Du hast also in deiner Anwendung keine große Möglichkeit anhand der Windowseinstellungen auf die Oracle einstellungen zu schließen. [1] Aber jetzt kommt der Punkt: Warum auch? Eine Number(10,4) kann in in einer DataColumn mit ähnlicher Formatierung abgebildet werden. SQL Statements sollten natürlich immer mit vernünftig typisierten Parametern erfolgen. Somit sollte es für dich niemals das Problem geben, dass du in deinem Code einen Dezimalwert als String benutzen willst. Die einzige Stelle wo das passiert ist in dem Control an das die Daten gebunden wurden. Stört dich aber im Code nicht weiter, weil es jede Eingabe verhindert, die nicht in den Zieltypen umgewandelt werden kann. Wie du bereits gemerkt hast, stellt das Datagrid nur die Dinge da, die du ihm als Datenquelle vorgibst, gib ihm einfach die richtigen Spaltentypen und alles ist in Butter... [1] Nicht lange darüber wundern: Oracle hat neben extrem komplexen und ähm coolen Features, soviele mittelalterliche und hirnrissige Macken und/oder Implementierungslücken, es würde Monate dauern die alle aufzulisten... :? |
Re: Fließkommazahlen Delphi vs. Oracle
Zitat:
|
Re: Fließkommazahlen Delphi vs. Oracle
Zitat:
btw: In dem Moment, in dem man sich dazu entschließt externe Dateien zu nehmen, ist man immer auch verplichtet sicherzustellen, dass die Werte auch wieder ausgelesen werden können. Hmpf? Nun, wenn ich mit deutschen Regionaleinstellungen eine Zahl in einen Text umwandel, erhalte ich "2,34", im englischen "2.34". Du musst also Standards vorgeben wie das zu passieren hat, oder bestehende standas benutzen. XML wäre hierfür natürlich ideal, aber selbst eine CSV-Datei ist nicht komplett witzlos, wenn man sich an die CSV-Standards hält (also nicht so wie Excel zum Bleispiel). Wenn dir die etwas komischen XMLs ausreichen, die ein DataSet auspsuckt, dann hast du das Speichern/Lesen von/zu XML schon ![]() |
Re: Fließkommazahlen Delphi vs. Oracle
Zitat:
Also ich benutze die Borland Data Provider und dort weise ich ja jedem Parameter seinen Wert zu (wie oben im kleinen Code-Schnipsel zu sehen). Angenommen ich wandle meinen eingelesenen String garnicht um, bekomme ich eine Fehlermeldung, dass es keine gueltige Zahl ist. Selbst wenn ich einem Parameter einen konkreten Doublewert zuweise, bekomme ich diese Fehlermeldung! Sobald ich wie gesagt meine NLS_NUMERIC_CHARACTERS in Delphi setzte, bekomme ich keinen Fehler mehr (das lässt mich wiederum daran zweifeln, dass es ein ORACLE-Problem ist!?) Zitat:
Das ganze kann doch nicht so kompliziert sein? Ich bin doch sicher nicht der erste, der Float-Werte in einer Datenbank speichern will!??? |
Re: Fließkommazahlen Delphi vs. Oracle
Zitat:
Es gab allerdings keine explizite Punkt-für-Punkt Anleitung. Aber um etwas genauer zu werden: Wenn du die Datei einliest kannst du mit ![]() Besonders beachten solltest du den Overload, der einen IFormatProvide bekommt. Hier mal etwas Pseudo code:
Delphi-Quellcode:
Natürlich willst du nicht ständig ein neues FormatInfo anlegen, aber das ist reine Implementierung und somit deine Sache. :P
var
deinNumberFormat : NumberFormatInfo; begin // Clone, weil wir ja nicht das Format für die ganze Anwendung verändern wollen! deinNumberFormat := CultureInfo.Create('de').NumberFormat.Clone() as NumberFormat; deinNumberFormat.Blabla // ändere die Eigenschaften, die du anders als in "de" brauchst ... einDecimal := Decimal.Parse('2,2', deinNumberFormat); |
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:33 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz