Der-Dennis: PDO und verkettete Parameter

Hallo zusammen,

ich hatte gerade ein Problem mit PDO. Ich wollte zwei Parameter über eine Funktion in _eine_ Spalte schreiben.
Weiß nicht recht wie ich's beschreiben soll. Also hier erst einmal, was ich prinzipell vorhatte:

  
$sql = "INSERT INTO tabelle (id, ...) VALUES ( MD5(:paramA:paramB), ...)";  
  
$query = $db->prepare($sql);  
$query->bindParam(':paramA', $paramA);  
$query->bindParam(':paramB', $paramB);  
$query->execute();  

Das hat weder auf meinem Localhost (MySQL 5.1.37) noch auf dem Webserver (MySQL 5.0.32) funktioniert.

Die Spalte id ist vom Typ Varchar mit Länge 32 und ist Primärschlüssel. Die Tabelle vom Typ MyISAM.

Als nächstes hatte ich folgendes probiert (man beachte das Leerzeichen zwischen :paramA und :paramB):

  
$sql = "INSERT INTO tabelle (id, ...) VALUES ( MD5(:paramA :paramB), ...)";  

Das funktionierte auf dem Localhost, nicht aber auf dem Webserver. Folgendes hingegen funktionierte auf beiden Servern (man beachte das Pluszeichen zwischen :paramA und :paramB):

  
$sql = "INSERT INTO tabelle (id, ...) VALUES ( MD5(:paramA+:paramB), ...)";  

Hat jemand eine Idee woran das liegen könnte? Ich kann weder in der PDO-Doku noch sonst im Netz etwas finden. Hat PDO sonst noch solche "Macken" (falls es denn eine sein sollte)?

Danke für Eure Antworten,

Gruß, Dennis

  1. Kurzer Nachtrag:

    Funktioniert nicht = altbekannter Fehler ("Fatal error: You have an error in your SQL syntax near...")

    Gruß, Dennis

  2. Hi!

    $sql = "INSERT INTO tabelle (id, ...) VALUES ( MD5(:paramA:paramB), ...)";

    Die beiden Platzhalter sind quasi wie Variablen zu betrachten. Wenn du sie verknüpfen willst, musst du schon angeben, welche der verschiedenen Verknüpfungsarten verwendet werden sollen.

    $sql = "INSERT INTO tabelle (id, ...) VALUES ( MD5(:paramA+:paramB), ...)";

    Möchtest du eine Addition oder eine Stringverknüpfung haben? Hast du dich vergewissert, dass das Ergebnis der MD5-Funktion das gleiche ist, wie wenn du statt der beiden Werte mal ein Literal nimmst, das dem Ergebnis deiner Verknüpfungsoperation entspricht?

    Lo!

    1. Hey dedlfix,

      danke für Deine Antwort!

      $sql = "INSERT INTO tabelle (id, ...) VALUES ( MD5(:paramA:paramB), ...)";

      Die beiden Platzhalter sind quasi wie Variablen zu betrachten. Wenn du sie verknüpfen willst, musst du schon angeben, welche der verschiedenen Verknüpfungsarten verwendet werden sollen.

      Das dachte ich auch. Hab's auch mit

        
      $sql = "INSERT INTO tabelle (id, ...) VALUES ( MD5(:paramA.:paramB), ...)";  
      
      

      probiert. Auch hier kommt der Fehler "You have an error in your MySQL Syntax...".

      $sql = "INSERT INTO tabelle (id, ...) VALUES ( MD5(:paramA+:paramB), ...)";

      Möchtest du eine Addition oder eine Stringverknüpfung haben? Hast du dich vergewissert, dass das Ergebnis der MD5-Funktion das gleiche ist, wie wenn du statt der beiden Werte mal ein Literal nimmst, das dem Ergebnis deiner Verknüpfungsoperation entspricht?

      Da bin ich grad natürlich wieder nicht drauf gekommen, hab's aber grad mal ausprobiert:

      Der MD5-Hash ist der gleiche, egal ob ich die Variablen an Parameter binde oder ob ich die Werte direkt ins SQL-Statement schreibe. Auch wenn ich die CONCAT-Funktion

        
      $sql = "INSERT INTO tabelle (id, ...) VALUES ( MD5( CONCAT(:paramA, :paramB)), ...)";  
      
      

      nehme ergibt das den gleichen Hash. Ich versteh's nicht, das Ergebnis scheint ja richtig zu sein. Nur erklären kann ich es nicht.

      Gruß, Dennis

      1. Nur erklären kann ich es nicht.

        Drösel doch einfach mal deine Versuche auf, 'foobar' an MD5() zu übergeben

        MD5(:paramA:paramB)
        MD5('foo''bar') # Syntaxfehler

        MD5(:paramA :paramB)
        MD5('foo' 'bar') # Syntaxfehler

        MD5(:paramA.:paramB)
        MD5('foo'.'bar') # Syntaxfehler

        MD5(:paramA+:paramB)
        MD5('foo'+'bar') # ist gleich mit MD5(0)

        MD5( CONCAT(:paramA, :paramB))
        MD5( CONCAT('foo', 'bar')) # jetzt ist es korrekt

        1. Hey DiBo33,

          auch Dir danke für Deine Antwort.

          Drösel doch einfach mal deine Versuche auf, 'foobar' an MD5() zu übergeben

          Hab ich grad noch mal gemacht.

          MD5(:paramA:paramB)
          MD5('foo''bar') # Syntaxfehler

          Wie im Ausgangsposting schon auch angemerkt: Syntaxfehler.

          MD5(:paramA :paramB)
          MD5('foo' 'bar') # Syntaxfehler

          Bei mir komischerweise kein Syntaxfehler:
          MD5(:paramA :paramB) => 3858f62230ac3c915f300c664312c63f
          MD5('foo' 'bar')     => 3858f62230ac3c915f300c664312c63f

          MD5(:paramA.:paramB)
          MD5('foo'.'bar') # Syntaxfehler

          Richtig.

          MD5(:paramA+:paramB)
          MD5('foo'+'bar') # ist gleich mit MD5(0)

          Ist auch korrekt. Ich hatte nur vermeintlich "richtige" Werte bekommen, weil mein Parameter A ein String mit einem Integer als Inhalt ist. Also so etwas wie $x = '123'; Manchmal ist man echt einfach zu blöd!

          MD5( CONCAT(:paramA, :paramB))
          MD5( CONCAT('foo', 'bar')) # jetzt ist es korrekt

          Ergibt bei mir das gleiche Ergebnis wie zweiten Beispiel: 3858f62230ac3c915f300c664312c63f. Auch wenn ich jetzt gesehen hab, wo mein Fehler war, versteh ich das trotzdem nicht. Ist MySQL hier wieder besonders nett und "verzeiht" einem so einen Fehler?

          Bei meinen Versuchen grade ist mir auch noch was anderes aufgefallen:

            
          $sql = "INSERT INTO tabelle (id, test) VALUES ( MD5( CONCAT(:paramA, :paramB)), :paramA)";  
          
          

          funktioniert nicht. Sprich: Die Spalte test wird mit '' gefüllt, obwohl :paramA einen Wert hat. Hingegen funktioniert

            
          $sql = "INSERT INTO tabelle (id, test) VALUES ( MD5(:paramA), :paramA)";  
          
          

          ohne Probleme. Darf ich, wenn ich CONCAT verwende den Parameter nicht zweimal nutzen? Oder ist es einfach schon zu spät und ich schreib am besten morgen mal weiter?

          Danke und Gruß, Dennis

          1. Bei mir komischerweise kein Syntaxfehler:
            MD5(:paramA :paramB) => 3858f62230ac3c915f300c664312c63f
            MD5('foo' 'bar')     => 3858f62230ac3c915f300c664312c63f

            Ist MySQL hier wieder besonders nett und "verzeiht" einem so einen Fehler?

            Scheint so

            SELECT 'foo' 'bar'

            ergibt anstandslos 'foobar'
            ist wohl wieder so eine Eigenheit von MySQL, wobei ich das bisher noch nicht dokumentiert gesehen habe.

            1. Hey DiBo,

              Ist MySQL hier wieder besonders nett und "verzeiht" einem so einen Fehler?

              Scheint so

              SELECT 'foo' 'bar'

              ergibt anstandslos 'foobar'
              ist wohl wieder so eine Eigenheit von MySQL, wobei ich das bisher noch nicht dokumentiert gesehen habe.

              danke für Deine Antwort. Aber wenn's auch bei Dir so ist, kann ich nur sagen, dass mich MySQL immer mehr nervt. Wie soll man denn so sauberen Code entwickeln? Wenn ich so etwas falsch mache, möchte auch einen Fehler bekommen. Ich möchte nicht, dass sich der Interpreter von MySQL "überlegt", was ich gemeint haben könnte sondern eine anständige Meldung a la "Das ist falsch und Du hast da folgenden Fehler begangen."

              Gruß, Dennis

      2. Hi!

        $sql = "INSERT INTO tabelle (id, ...) VALUES ( MD5(:paramA.:paramB), ...)";

        Ein . ist kein Operator in MySQL. Er wird nur für Bezeichner-Qualifizierungen verwendet.

        Der MD5-Hash ist der gleiche, egal ob ich die Variablen an Parameter binde oder ob ich die Werte direkt ins SQL-Statement schreibe.

        Bei welcher Operation genau und wie lautet der Hash? Das Ergebnis von MD5(0) und MD5('foo' + 'bar') ist übrigens beides Mal cfcd208495d565ef66e7dff9f98764da. Kannst du dir denken warum?

        Auch wenn ich die CONCAT-Funktion
        $sql = "INSERT INTO tabelle (id, ...) VALUES ( MD5( CONCAT(:paramA, :paramB)), ...)";
        nehme ergibt das den gleichen Hash.

        Es müssen dann aber auch bei unterschiedlichen angebunden Wert verschiedene Hashes entstehen.

        Lo!

        1. Hey dedlfix,

          $sql = "INSERT INTO tabelle (id, ...) VALUES ( MD5(:paramA.:paramB), ...)";

          Ein . ist kein Operator in MySQL. Er wird nur für Bezeichner-Qualifizierungen verwendet.

          danke, das ist mir bekannt. Ich hab's einfach nur noch ohne Nachzudenken mit "try and error" versucht, weil ich einfach keine Lust mehr hatte.

          Der MD5-Hash ist der gleiche, egal ob ich die Variablen an Parameter binde oder ob ich die Werte direkt ins SQL-Statement schreibe.

          Bei welcher Operation genau und wie lautet der Hash? Das Ergebnis von MD5(0) und MD5('foo' + 'bar') ist übrigens beides Mal cfcd208495d565ef66e7dff9f98764da. Kannst du dir denken warum?

          Ja! Und danke, dass Ihr mich auf den richtigen Weg gebracht habt. Wie ich in meiner anderen Antwort schon geschrieben habe war ich einfach zu blöd das zu erkennen.

          Auch wenn ich die CONCAT-Funktion
          $sql = "INSERT INTO tabelle (id, ...) VALUES ( MD5( CONCAT(:paramA, :paramB)), ...)";
          nehme ergibt das den gleichen Hash.

          Es müssen dann aber auch bei unterschiedlichen angebunden Wert verschiedene Hashes entstehen.

          Das hat es auch. Hab mich da wohl falsch ausgedrückt. Ich meinte, "CONCAT(:paramA, :paramB)" und ":paramA :paramB" ergeben bei gleichen Parametern den gleichen Wert.

          Gruß, Dennis