2009-11-17 11 views
8

Ich muss eine Zeile mit PHP mysql verbesserte Bibliothek in eine Tabelle in mysql einfügen, die ihren Primärschlüssel vom Typ VARBINARY hat. Der Inhalt dieses Felds ist ein berechneter sha1-Hash.PHP - Einfügen von Binärdaten in mysql mit vorbereiteten Anweisungen

Wenn ich die Abfrage auf die alte Weise laufen funktioniert es perfekt:

$mysqli->$query("INSERT INTO table (id, field1) VALUES (0x" . $id . ",'" . $field1 . "')"); 

Aber wenn ich versuche, es als eine vorbereitete Anweisung auszuführen, kann ich nicht herausfinden, wie es zu tun. Wenn führe ich die entsprechende Aktion:

if($stmt = $mysqli->prepare("INSERT INTO table (id, field1) VALUES (?, ?)")) { 
    $stmt->bind_param('ss', "0x".$id, $field1); 
    //execute statement 
} 

Es löst eine Ausnahme zu sagen, dass die Inhalte für diesen Bereich zu groß waren. Und wenn ich versuche, es als ein BLOB-Feld einzufügen:

if($stmt = $mysqli->prepare("INSERT INTO table (id, field1) VALUES (?, ?)")) { 
    $stmt->bind_param('bs', $id, $field1); 
    //execute statement 
} 

Es gibt keinen Fehler, wird die Zeile eingefügt, aber das Kennungsfeld nun leer ist (nicht null, leer).

Ich weiß, ich kann die Abfrage mischen und geben Sie die ID in der Zeichenfolge und die anderen Felder als Bindeparameter der vorbereiteten Anweisung verkettet, aber ich frage nur, um zu wissen, was ist der richtige Weg, um dies und vielleicht es einfügen wird jemandem in der Zukunft helfen.

+0

Welche Werte haben Sie für $ id und field1 $, wenn Sie dies tun? Ist $ id eine ganze Zahl? Wenn ja, hast du versucht, es als solches zu binden? 'stmt-> bind_param ('is', $ id, $ field1);' – nash

+0

Der Wert von $ id ist ein sha1-Hash. Es ist keine ganze Zahl. Die anderen Felder verursachen das Problem nicht, sondern sind hauptsächlich Zeichenfolgen. –

+0

Plus eine für den Versuch, die Sicherheit der vorbereiteten Anweisungen beizubehalten, während dieses Problem gelöst wird. – HoldOffHunger

Antwort

6

PHP sha1 Funktion gibt eine Zeichenfolgendarstellung einer Hex-Zahl.

Dies bedeutet, dass wenn Sie es auf dem Bildschirm drucken, wird es eine Hex-Nummer angezeigt. Aber im Speicher ist es eine Reihe von ASCII-Zeichen. Geben Sie die Hex-Nummer 1A2F ein. Als ASCII im Speicher wäre das 0x31413246 anstelle von 0x1A2F

MySQL normale Schnittstelle sendet alle Argumente als Zeichenfolgen. Wenn Sie die normale Schnittstelle verwenden, konvertiert MySQL die ASCII-Zeichenfolge in einen binären Wert.

Die neue vorbereitete Anweisungsmethode sendet alles als Binärdatei. Ihr schöner Wert von "1A2F" wird nun als 0x31413246 gesendet und in die Spalte eingefügt. - source: dev.mysql.com - Prepared statements

Stattdessen wandeln Sie Ihre Hex-String, indem sie in eine binäre Zeichenfolge Verpackung mit:

$binId = pack("H*", $id); // this string is not ASCII, don't print it to the screen! That will be uggly. 

und dann $binId passieren zu der MySQLi Rechnung statt $ id.

+0

Sie haben Recht. Dies ist der Weg, es zu tun. Vielen Dank. –

+0

Ich habe mich selbst gefragt! Ich wollte nur anmerken, dass Sie 'hex2bin' auch als eine praktische Alternative zu' pack' verwenden können und ebenso 'bin2hex' verwenden können, wenn Sie die Daten wieder herausziehen (anstatt' HEX() 'in Ihrer Anweisung zu verwenden). – Haravikk

3

versuchen Sie stattdessen:

if($stmt = $mysqli->prepare("INSERT INTO table (id, field1) VALUES (unhex(?), ?)") { 
    $stmt->bind_param('ss', $id, $field1); 
    //execute statement 
} 
0

tl; dr: auschecken send_long_data().

Ich weiß, das ist eine sehr alte Frage, aber es war genau was ich versuchte zu tun und scheiterte an. Nachdem ich die obigen Antworten ausprobiert und viel Zeit mit dem Experimentieren verbracht hatte, fand ich endlich etwas, das so funktionierte, wie die Frage und ich es versuchten.

Es ist verwirrend, weil die einzige Referenz für die mit „b“ Typen in den PHP bind_param documentation indirekt gehen ist, wenn auf Daten, die die zulässige Paketgröße übersteigt (was ich übersprungen zunächst):

Wenn die Datengröße einer Variablen größer ist als zulässige Paketgröße (max_allowed_packet), müssen Sie b in Typen angeben und verwenden mysqli_stmt_send_long_data() die Daten in Pakete zu senden.

Es stellt sich heraus, dass binäre Typen von selbst gesendet werden müssen, bevor Sie Ihre Einfügung ausführen. Ich fand das aus einer article from Oracle's website heraus.

Da sie es erklären, so kurz und bündig, werde ich paraphrasieren nur den relevanten Teil:

den Blob Speichern

Hier ist der Code ein Blob speichern MySQLi mit:

Ich fette zwei Stücke Code, die ich th Tinte ist lohnt einen Blick auf:

Die $ null Variable benötigt wird, weil bind_param() immer eine variable Referenz für einen bestimmten Parameter will. In diesem Fall der Parameter "b" (wie in Blob). Also $ null ist nur ein Dummy, um die Syntax zu arbeiten.

Im nächsten Schritt muss ich meinen Blob-Parameter mit den eigentlichen Daten "füllen". Dies geschieht durch send_long_data(). Der erste Parameter von Diese Methode gibt an, welchem ​​Parameter die Daten zugeordnet werden. Die Parameter sind mit 0 beginnend nummeriert. Der zweite Parameter send_long_data() enthält die tatsächlichen zu speichernden Daten.

Bei der Verwendung von send_long_data(), stellen Sie sicher, dass der Blob nicht ist größer als MySQL max_allowed_packet

Verwandte Themen