Information ausblenden
Willkommen im Forum für alle Datenbanken! Registriere Dich kostenlos und diskutiere über DBs wie Mysql, MariaDB, Oracle, Sql-Server, Postgres, Access uvm

Bei Prepared Statement Zeichen ersetzen

Dieses Thema im Forum "MySQL und MariaDB" wurde erstellt von exzel, 3 Dezember 2013.

  1. exzel

    exzel Datenbank-Guru

    Hallo zusammen,

    derzeit probiere ich gerade Prepared Statements aus. Bei einer gewöhnlichen INSERT oder UPDATE Anweisung kann ich durch REPLACE ein Zeichen durch ein anderes ersetzen. In meinem Fall handelt es sich um ein HTML Eingabefeld (Beitragsfeld), in dem ein Beitrag mit Tausender- und Dezimaltrennzeichen eingegeben werden kann. MySQL lehnt ein Komma ab.

    Im folgenden Thread wurde mir der Tip mit Replace gegeben.

    http://datenbankforum.com/threads/in-insert-anweisung-zeichen-ersetzen.408/

    Soweit so gut. Doch leider klappt das die Replace Anweisung bei den Prepared Statements nicht. Oder vielleicht mache ich was falsch. Hier der Code für den Button zum Übernehmen der eingetragenen Ziel auf der HTML-Seite.

    Code:
    if($_POST['uebernehmen'])
    {
        $stmt=$mysqli->prepare($insertziele);
        $stmt->bind_param("sdddddddddddddd",
        $uid,
        $_POST['ziel1'],
        $_POST['ziel2'],
        $_POST['ziel3'],
        $_POST['ziel4'],
        $_POST['ziel5'],
        $_POST['ziel6'],
        $_POST['ziel7'],
        $_POST['ziel1'],
        $_POST['ziel2'],
        $_POST['ziel3'],
        $_POST['ziel4'],
        $_POST['ziel5'],
        $_POST['ziel6'],
        $_POST['ziel7']);
        $stmt->execute();
    }
    Code:
    $insertziele="INSERT INTO zielema (jahr, id_betreuer, ziel1, ziel2, ziel3, ziel4, ziel5, ziel6, ziel7) VALUES (2013,?,?,?,?,?,?,?,?)
    ON DUPLICATE KEY UPDATE
    ziel1= REPLACE(REPLACE(?, '.' , ''), ',' , '.'),
    ziel2= ?,
    ziel3= ?,
    ziel4= ?,
    ziel5= ?,
    ziel6= ?,
    ziel7= ?;";
    Die innere Replace Funktion löscht beim eingetragenen Wert den Punkt, während die äußere das Komma durch den Punkt ersetzt. Somit ist der Wert SQL tauglich und korrekt gespeichert. Damit die Ausgabe wieder Punkt und Komma anzeigt habe ich über PHP das Ausgabefeld formatiert.

    Aber die Nachkommastellen werden immer durch 0 ersetzt. Also aus 555,55 wird beim ersten Übernehmen 555,00. Was läuft falsch?

    Gruß und Dank!
     
  2. akretschmer

    akretschmer Datenbank-Guru

    An der Stelle kann man mit lesen aufhören. Wie die DB etwas speichert, ist das eine. Dazu nutzt sie das, was sie kann. Wie es ausgegeben wird, ist eine andere Geschichte. Dezimaltrennzeichen, Tausender-Dingens, 12- oder 24 - Stunden - Darstellung, Dezember oder December - alles für die interne Speicherung egal. Dazu gibt es (in richtigen Datenbanken zumindest) passende Ausgabe-Formatier-Funktionen. Nutze diese, und gut ist.
     
  3. exzel

    exzel Datenbank-Guru

    Hallo,

    das habe ich nicht ganz verstanden.

    Also in das HTML-Feld wird 12345,12 geschrieben. Die Datenbank würde die Zahl so nicht anerkennen. Die Spalte in der Datenbank ist nämlich vom Typ decimal. Somit verarbeitet mysql diese Zahl nicht korrekt. Was soll die korrekte Ausgabe-Formatier-Funktionen helfen?

    Gruß und Dank!
     
  4. akretschmer

    akretschmer Datenbank-Guru


    Ah, ich war im ersten Post vom Schluß her davon ausgegangen, daß es Dir um die Ausgabe mit Gruppen-und Dezimaltrenner ging.

    Also um:
    Code:
    test=# create table excel (f double precision);
    CREATE TABLE
    test=*# insert into excel values(1);
    INSERT 0 1
    test=*# insert into excel values(12345.12);
    INSERT 0 1
    test=*# select to_char(f, '99G999D99') from excel;
      to_char
    ------------
      1,00
      12.345,12
    (2 rows)
    
    test=*# show lc_numeric;
     lc_numeric
    -------------
     de_DE.UTF-8
    (1 row)
    
    test=*# set lc_numeric to 'en_US.UTF-8';
    SET
    test=*# select to_char(f, '99G999D99') from excel;
      to_char
    ------------
      1.00
      12,345.12
    (2 rows)
    
    Aber Du willst das ja vor der Eingabe umwandeln, oder?

    Code:
    test=*# set lc_numeric to 'de_DE.UTF-8';
    SET
    test=*# select to_number('12345,67','999999D99');
     to_number
    -----------
      12345.67
    (1 row)
    

    Ich weiß nicht, ob MySQL und/oder PHP da schon passende Funktionen her haben.

    Der Insert klappt? Wass steht denn in der DB dann drin, sind da noch die Nachkommastellen, oder fehlen sie da schon?
     
  5. ukulele

    ukulele Datenbank-Guru

    Ist eventuell das Format der Spalte ohne Nachkommastellen angelegt?
     
  6. exzel

    exzel Datenbank-Guru

    Hallo und danke für die Rückmeldungen!

    Also die Spalte ist mit decimal(11,2) angelegt. Der Insert bzw. Update klappt bei folgendem Code

    PHP:
    ....
    ziel1REPLACE(REPLACE(?, '.' ''), ',' '.'),
    .....
    (siehe oben) folgendermaßen.

    Ich gebe 5555,55 ein und führe den Query aus. Es wird dann 5555,00 in der DB gespeichert. Auch bei mehrfacher Ausführung. Die zwei Nullen werden in der DB angezeigt.

    Ändere ich den obigen Code auf

    PHP:
    ....
    ziel1=?,
    .....
    und wiederhole das ganze mehrfach wird aus 5555,55 ->5555,00->5,56->5,00.

    Vollständigerweise muss ich sagen, dass die Ausgabe über PHP formatiert wird.
    PHP:
    echo number_format($zielefeld['ziel1'], ',' '.')

    Gestern habe ich das ganze nochmals ohne Prepared Statements probiert.

    Code:
    $updatetest="UPDATE zielema SET ziel1 = REPLACE(REPLACE('{$_POST['ziel1 ']}', '.' , ''), ',' , '.');";
    So wird einwandfrei die Zahl korrekt umgewandelt und gespeichert in der DB. Warum das in dem Prepared Statement nicht funktioniert ist mir ein Rätsel. Im schlimmsten Fall muss ich halt die Formatierung über PHP machen. Oder gibt es noch Lösungsansätze über die DB?

    Gruß und Dank!
     
  7. akretschmer

    akretschmer Datenbank-Guru

    Aus dem ersten Post:

    Code:
    $stmt->bind_param("sdddddddddddddd", $uid, $_POST['ziel1'], $_POST['ziel2'],
    
    Du definierst die Parameter als 'd', die Werte in POST['ziel1'] etc. sind aber Strings, ohne jetzt viel Ahnung von PHP zu haben denke ich, das geht so schon nicht.

    Im ersten Post scheint es, als ob es nicht gewollt ist, daß da die Nachkommastellen zu 0 werden, jetzt schreibst aber:

    "Der Insert bzw. Update klappt bei folgendem Code" ...
    "Ich gebe 5555,55 ein und führe den Query aus. Es wird dann 5555,00 in der DB gespeichert. Auch bei mehrfacher Ausführung. Die zwei Nullen werden in der DB angezeigt."

    Klingt für mich, als ob das genau das ist, was Du willst.


    Ich würde ja direkt mit SQL ein Prepare auf der DB machen, sagen, daß da ein String kommt, und in der DB mit to_number() arbeiten.

    Code:
    test=# create table x(val double precision);
    CREATE TABLE
    test=*# prepare insert_x as insert into x (val) values (to_number($1, '9999999D99'));
    PREPARE
    test=*# execute insert_x('12345,67');
    INSERT 0 1
    test=*# select * from x;
      val
    ----------
     12345.67
    (1 row)
    
    Aber ich kenne MySQL und mysqli als PHP-Schnittstelle zu wenig, um da einen richtigen Weg Dir vorschlagen zu können.
     
    ukulele gefällt das.
  8. exzel

    exzel Datenbank-Guru

    Also so wie ich das verstanden habe, muss ich den Typ im Prepared Statement angeben, der in der Datenbankspalte hinterlegt ist. In der Datenbank sind die Ziele als decimal(11,2) also muss ich auch d im Prepared Statement angeben. Und die Ziele weren auch also Kommazahlen angegeben. So müsste es doch passen, oder?

    Trotzdem danke!
     
  9. akretschmer

    akretschmer Datenbank-Guru

    Denke ich mal, ja.

    Nee, weil dann paßt der Typ nicht. Ich weiß nicht, wie man das in PHP löst. Bei meiner alten Arbeit hab ich etwas mit PHP gespielt, hier und jetzt nicht mehr.
     
  10. exzel

    exzel Datenbank-Guru

    Bist du dir sicher, dass der Typ nicht passt. Also obwohl eine Dezimalzahl in das HTML-Eingabefeld eingegeben war, ist der Typ decimal im Prepared Statement falsch. Warum?
     
  11. akretschmer

    akretschmer Datenbank-Guru

    Du denkst zu sehr deutsch. Ein String mit Komma wird nicht automatisch eine Zahl, nur weil hier bei uns das Komma der Dezimaltrenner ist.

    Code:
    test=# select '1234.56'::decimal;
     numeric
    ---------
     1234.56
    (1 row)
    
    Time: 40,536 ms
    test=*# select '1234,56'::decimal;
    ERROR:  invalid input syntax for type numeric: "1234,56"
    LINE 1: select '1234,56'::decimal;
      ^
    Time: 0,184 ms
    test=*#
    
    Auch wenn ich MySQL ned mag, das dürfte da exakt genauso sein (inhaltlich, CAST-Syntax ist da wohl anders. In PG ist decimal nur ein Synonym für numeric)
     
  12. exzel

    exzel Datenbank-Guru

  13. ukulele

    ukulele Datenbank-Guru

    Ich wüsste auch keinen Weg SQL beizubringen ein Komma als Dezimaltrennzeichen zu akzeptieren daher wäre meine erste Intuition auch das per replace() oder so zu wechseln.
     
  14. exzel

    exzel Datenbank-Guru

    Hallo,

    ja, das dachte ich auch aber REPLACE funktioniert bei mir eben nicht in Kombination mit einem Prepared Statement. Bei einem gewöhnlichem Query schon. Keine Ahnung warum.
     
  15. akretschmer

    akretschmer Datenbank-Guru

    Du kannst nicht direkt alles mit prepared Dinges machen, so z.B. auch nicht: select * from foo where id in (1,2,3), weil prepared heiß ja auch, daß die Anzahl der Parameter zum prepare-zeitpunkt feststeht. Wenn Du da also beim prepare mit ... id in (?) arbeitest und dann aber '1,2,3' übergibst, dann sind das plötzlich 2 Paraneter zu viel. Vermutlich passiert hier exakt dasselbe.
     
Die Seite wird geladen...

Diese Seite empfehlen

  1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies.
    Information ausblenden