HELP! Bin ich doof? Wie Kommawert aus php in Datenbank???

falkgottschalk

Aktives Mitglied
Thread Starter
Dabei seit
22.08.2005
Beiträge
24.076
Reaktionspunkte
1.619
Hallo,

irgendwie stehe ich heute total auf dem Schlauch.
Ich will einfach nur in eine mysql-Tabelle einen numerischen Wert mit Nachkommastellen reinschreiben.

Auszug aus dem Coding:


PHP:
$brutto = "36.8";
//$brutto = 184 / 5;

    $sql = 'UPDATE ergebnis SET
    brutto = "' . $brutto . '" '.
    ' where spielerUID = "' . $spielerUID . '" ';
$update =  mysql_query($sql);
    if (!$update)

Wenn ich das so ausführe wie es hier steht, dann ist in der Datenbank auch der Kommawert drin.
Mache ich die // in der zweiten Zeile raus (mathematisch gesehen kommt dann auch 36.8 heraus) steht in der Datenbank nur die 36 und die ,8 fehlen.

Warum? Wieso?
Das kann doch nur eine Kleinigkeit sein..

Danke!
 
Ich kennen PHP nicht so genau, aber vermutlich wird hier einfach eine Ganzzahldivision durchgeführt mit Rundung.
Versuchs doch mal mit
$brutto =184.0 / 5.0
 
PHP:
//$brutto = "36.8"; 
$brutto = 184 / 5;
$brutto = floatval($brutto);

klappt es vielleicht so?
 

Hilf mir bitte mal auf die Sprünge, denn momentan verstehe ich auch nicht so ganz, was da passiert; und auch nicht, was das mit den MySQL-Datentypen zu tun hat:

Also, ist ersten Fall ($brutto = "36.8") ist $brutto erstmal ein String, in zweiten Fall ($brutto = 184 / 5) eine Fließkommazahl.

Falls das MySQL-Feld brutto vom Typ FLOAT ist, sollte auch in beiden Fällen 36.8 in der DB landen.
Falls das MySQL-Feld brutto vom Typ STRING ist, sollte doch ebenfalls in beiden Fällen 36.8 gesichert werden, oder?
Denn schließlich wird die Variable $brutto, egal von welchem Typ, von PHP in einen String konvertiert, sobald sie in die Variable $sql »eingebettet« wird.

Nur, wenn das MySQL Feld z.B. vom Typ INT ist, sollte die 36 ohne Nachkomma gesichert werden – aber dann wiederum in beiden Fällen…
 
da er ja den feld typ nicht genannt hat, ging ich halt davon aus, dass es INT ist...
 
Nein, kein INT.
Ich hatte es sowohl mit DECIMAL als auch FLOAT probiert.
Im phpmyadmin stand ja nach der ersten Version auch die Kommazahl drin.

Ich habe es dann hiermit gelöst:


$brutto = str_replace(',', '.', $brutto);

es wundert mich aber schon etwas, dass man errechnete Werte nicht einfach in die Datenbank schreiben kann... :teeth:
 
Liegt das evtl. An den Spracheinstellungen? Komma = deutsch, Punkt = englisch?
 
es wundert mich aber schon etwas, dass man errechnete Werte nicht einfach in die Datenbank schreiben kann... :teeth:

Normalerweise kann man das, wirklich – ich hab das schon in etlichen Skripten gemacht.
Deshalb kapiere ich ja auch nach wie vor nicht, was bei Dir falsch läuft; würde aber mal in die von robertm vorgeschlagene Richtung weiterforschen.
 
Theoretisch würde ich Euch ja recht geben wollen mit dem Punkt und dem Komma - aber das kann doch bei mathematischen Operationen keine Auswirkung haben, oder???
 
Doch! Wenn du das falsche Dezimalzeichen mitgibst haben praktisch alle Programmiersprechen und Datenbanken Probleme. Mach mal in Java ein new Float(3,5) statt new Float(3.5), dann wirst du es sehen. Und hier machst du auch keine mathematische Opertion sondern eine Zuweisung.

Es gibt doch in PHP die diversesten Konvertierungsfunktionen (hab sie jetzt nicht mehr parat). Da gibt's bestimmt auch ein String-To-Float....
 
Theoretisch würde ich Euch ja recht geben wollen mit dem Punkt und dem Komma - aber das kann doch bei mathematischen Operationen keine Auswirkung haben, oder???

Doch, doch.
Hab’s jetzt gerade mal ausprobiert; wenn Du PHP dazu veranlasst, das Komma als Dezimaltrennzeichen zu nehmen, z.B. per
PHP:
setlocale(LC_ALL, 'de_DE');

… dann lautet der Inhalt von $sql folgendermaßen:
UPDATE ergebnis SET brutto = "36,8" where (…)
… und nicht, wie normalerweise:
UPDATE ergebnis SET brutto = "36.8" where (…)

Denn aufgrund der setlocale-Einstellung liefert PHP das Ergebnis einer Rechnung halt mir Komma zurück – anders als bei $brutto = "36.8", wo Du den Punkt ja von Hand eingetragen hast.

Für MySQL ist das Komma aber weiterhin kein Dezimaltrennzeichen; und führt dazu, dass beim Feldtyp FLOAT das »,8« halt abgeschnitten wird und nur die 36 in der DB landet.

Also: Entweder dafür sorgen, dass die setlocale-Einstellung (wo auch immer die her kommt) auf Default-Werte zurückgesetzt wird – oder, wie Du es jetzt schon gemacht hast, vor dem Query das Komma durch einen Punkt ersetzen.



Edit: Upps, zu langsam, der Link von robertm sagt schon alles…
 
Ähm, danke an alle für die ausführlichen Erklärungen.
Dass php wirklich schon beim Rechnen solche Sachen macht … bei der Ausgabe kann ich es ja verstehen, aber beim Rechnen?
Naja, mal lernt halt nie aus. Die sauberste Lösung dürfte das mit dem setlocale sein.
 
falkgottschalk schrieb:
Dass php wirklich schon beim Rechnen solche Sachen macht … bei der Ausgabe kann ich es ja verstehen, aber beim Rechnen?

Das sind gleich zwei Fallen auf einmal! Dezimaltrenner ist der "." (per Default). PHP rechnet aber leider eben wg. der typenlosen Variablen auch mit Strings. Sonst hätte es für Dich ja eh einen Fehler gegeben (bei "36.8" auch). Nun ist "36,8" in jedem Fall ein String und PHP verwendet alles womit man rechnen kann und das klappt bis zum ersten fehlerhaften Zeichen ( eben dem Komma). Der numerische Wert von "36,8" ist also 36! Das heißt PHP mag typenlos arbeiten, Du als Programmierer mußt daher aber mehrfach genau gucken ob Du da wirklich die Werte bekommst die Du erwartest.

Die zweite Falle: Float und Double sind nur bedingt genaue Repräsentanzen. Gerade bei Rundungswerten ( auf Cent ) kann es vorkommen, daß Du einen Betrag schreibst und einen anderen später wieder ausliest. Sprich: float und Double sind Näherungsintervalle und es klappt nicht immer exakt den Wert zu speichern den Du erwartest. Bei anderen DBMS ( etwa bei Postgres oder MS SQL) würdest Du haufenweise solche impliziten Fehler bekommen, MySQL macht es richtig und gehört damit aber zu einer Minderheit by DB-Systemen! Einige DBs haben daher einen Extra-Datentyp Money. Fehlerfreier ist es, wenn Du gleich in Ganzzahlen speicherst. Ich speichere Geldbeträge immer in Cent und die zugehörigen Objekte haben bei mir alle eine getAsEuro();-Methode. Zu Float/Double habe ich hier ein Beispiel in Punkt 2.
 
Zuletzt bearbeitet:
Dass php wirklich schon beim Rechnen solche Sachen macht … bei der Ausgabe kann ich es ja verstehen, aber beim Rechnen?

PHP macht das ja nur bei der Ausgabe!

Nehmen wir mal folgenden Codeschnippsel:
PHP:
<?php
$loc_de = setlocale(LC_ALL, 'de_DE');
$a = "5,5";
$b = "3,3";
$c = $a + $b;
echo "Ergebnis: $c";
?>

Ganz egal, ob Du die setlocale-Einstellung so lässt wie in diesem Schnippsel, ob Du sie auf 'en_US' setzt oder die Zeile ganz weglässt: Als Ergebnis bekommst Du 8 präsentiert – die Nachkommastellen werden beim Rechnen also auf jeden Fall weggelassen, weil es sich für PHP eben nicht um eine Fließkommazahl handelt.

Ändert Du Zeile 2 und 3 hingegen folgendermaßen ab:
PHP:
$a = "5.5";
$b = "3.3";

Dann bekommst Du, abhängig von der setlocale-Einstellung, entweder 8,8 oder 8.8 als Ergebnis geliefert.

Das »Problem« bei Deinem Skript-Auszug ist halt, dass Du mit
PHP:
$brutto = 184 / 5;
das Ergebnis, welches PHP (nach gewünschter lokaler Formatierung!) zurückliefert, »einfängst« und dann in den Query einsetzt.

In der Praxis hat das natürlich kaum eine Auswirkung, denn selbst wenn Du Deinen Query so schreibst:
PHP:
$sql = 'UPDATE ergebnis SET 
brutto = "' . (184 / 5) . '" '. 
' where spielerUID = "' . $spielerUID . '" ';

… wird abermals nur die (von setlocale beeinflusste) Ausgabe der Rechnung in den Query eingesetzt.
Die interne Rechnung arbeitet aber immer mit dem Punkt als Dezimaltrennzeichen.
 
Ähm - ah, jetzt, ja. Oder auch nicht...
Irgendwie stehe ich da immer noch von der Einsicht her auf dem Schlauch:
Wenn ich mir aus einer DB-Tabelle einen Dezimal-Wert mit Nachkommastellen rausnehme, z.B. so:
PHP:
select ... 
$wert1 = mysql_result($result,0,'wert1');
$wert2 = mysql_result($result,0,'wert2');

$wert3 = wert1 / wert2;

dann finde ich es einmalig bekloppt dass beim Rechnen dann der nur für die Ausgabe interessante Punkt/Komma-Thema eine Rolle spielt...

Irgendwie ist das doof. :(

(Tagsüber programmiere ich in SAP herum, da hat man solche Probleme nicht. :Pah:)

Herzlichen Dank für die ganzen Erklärungen...
 
Wenn ich mir aus einer DB-Tabelle einen Dezimal-Wert mit Nachkommastellen rausnehme, z.B. so:
PHP:
select ... 
$wert1 = mysql_result($result,0,'wert1');
$wert2 = mysql_result($result,0,'wert2');

$wert3 = wert1 / wert2;

dann finde ich es einmalig bekloppt dass beim Rechnen dann der nur für die Ausgabe interessante Punkt/Komma-Thema eine Rolle spielt...

Hab ich noch nicht probiert, ob sich die setlocale-Einstellungen auch auf einen MySQL-Result bezieht – aber wenn Du das sagst…


Irgendwie ist das doof. :(
(Tagsüber programmiere ich in SAP herum, da hat man solche Probleme nicht. :Pah:)

Ich bin sicher: Wenn Du SAP sagst, dass es Fließkommawerte mit Komma statt Punkt formatieren sollst, macht es das auch. ;)

Anders ausgedrückt: Es ist kein Standard, dass die setlocale-Einstellungen so gesetzt sind. Soweit ich weiß, kann man diese Einstellungen auch nur zur Laufzeit setzen (also nicht in der php.ini), so dass zu vermuten ist, dass irgendwo in Deinem Script eine entsprechende Zeile zu finden ist.
 
Ich bin sicher: Wenn Du SAP sagst, dass es Fließkommawerte mit Komma statt Punkt formatieren sollst, macht es das auch. ;)

Naja, um so einen Mumpitz muss ich mich doch in der SAP-Welt nicht kümmern. :Pah:
Intern wird mit Fliesskommazahlen gerechnet, rein numerisch. Bei der Ausgabe, die SAP selber steuert, kann man ein Feld definieren aus dem standardmäßig die Währung genommen wird (natürlich pro Tabelle bzw. pro Beleg) und die Ausgabe am Bildschirm oder Drucker wird dann entsprechend formatiert, incl. Land der Ausgabe-Kommunikationssprache.
(In Englisch gedruckte Belege, de Rupien als Betrag ausweisen, sieht das mit Komma/Punkt anders aus als wenn ich das in deutscher Sprache drucke.)

Anders ausgedrückt: Es ist kein Standard, dass die setlocale-Einstellungen so gesetzt sind. Soweit ich weiß, kann man diese Einstellungen auch nur zur Laufzeit setzen (also nicht in der php.ini), so dass zu vermuten ist, dass irgendwo in Deinem Script eine entsprechende Zeile zu finden ist.

Ja, so eine Zeile habe ich gefunden. Ich war aber SAP-verwöhnt und ging davon aus, dass sich das nur auf die Ausgabe am Bildschirm beziehen würde.
OK, ich sollte etwas mehr Doku lesen...
 
falkgottschalk schrieb:
Ich war aber SAP-verwöhnt und ging davon aus, dass sich das nur auf die Ausgabe am Bildschirm beziehen würde.

naja das geht ja auch, wenn Du die Zahlen erst für die Ausgabe formatierst wie Du sie haben willst ( number_format() ist da Dein Freund ) und ansonsten den Standard-Operator für die Dezimaltrennung ( und das ist eigentlich immer der ".", nicht nur in PHP) verwendest. Nochmal der Hinweis das es eh gesünder ist in Cent zu speichern und einen Bogen um Float/Double zu machen wenn exakte Werte gefragt sind ( was bei Geld ja meist der Fall ist).
 
Zurück
Oben Unten