2009-11-17 16 views
8

PHPのmysql改良ライブラリを使用して、VARBINARY型の主キーを持つmysqlのテーブルに行を挿入する必要があります。 このフィールドの内容は、計算されたsha1ハッシュです。PHP-プリペアドステートメントを使用してmysqlにバイナリデータを挿入する

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

をしかし、私は準備されたステートメントとして、それを実行しようとしたとき、私はそれを行う方法を見つけ出すことはできません:私は、クエリに古い方法を実行した場合

は、それが完璧に動作します。

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

それは内容がこのフィールドに対して大きすぎたという例外がスローされます: 場合、私は同等のアクションを実行します。私は、BLOBフィールドとしてそれを挿入しようとすると:

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

それは何のエラーを与えていない、行が挿入されますが、識別子フィールドは現在(空、nullではない)空です。

私はクエリをミックスして、文字列に連結したIDと準備されたステートメントのバインドパラメータとして他のフィールドを入力することができますが、私はちょうどこれとおそらくそれを挿入する正しい方法がわかっています将来誰かを助けるでしょう。

+0

何の値あなたは$ IDと$フィールド1のために持っていないことを確認してください? $ idは整数ですか?もしそうなら、そのようにバインドしてみましたか? 'stmt-> bind_param( 'is'、$ id、$ field1); ' – nash

+0

$ idの値はsha1ハッシュです。これは整数ではありません。他のフィールドは問題の原因ではありませんが、主に文字列です。 –

+0

この問題を解決しながら準備済みステートメントのセキュリティを維持しようとするものに加えて、 – HoldOffHunger

答えて

6

PHPのsha1機能が進数の文字列表現を返します。

つまり、画面に印刷すると、16進数が表示されます。しかし、メモリ内では、それはASCII文字の束です。

したがって、16進数の数字は1A2Fです。メモリ内のASCIIとして、0x1A2Fの代わりに

の代わりに0x31413246のように、すべての引数を文字列として送信します。通常のインターフェイスを使用する場合、MySQLはASCII文字列をバイナリ値に変換します。

新しいプリペアドステートメントメソッドは、すべてをバイナリとして送信します。だからあなたの素晴らしい値 "1A2F"は0x31413246として送信され、列に挿入されます。

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

をしてMySQLiを代わりに$のIDの声明を準備し、その後$binIdを渡す: - source: dev.mysql.com - Prepared statements

代わりに、使用してバイナリ文字列にそれを梱包して、16進文字列に変換します。

+0

あなたは正しいです。これがその方法です。どうもありがとうございました。 –

+0

これは自分自身が不思議でした! 'pack'の代わりに' hex2bin'を使うこともできますし、 'HEX()'を使わずにデータを取り出すときに 'bin2hex'を使うこともできます。 – Haravikk

3

は、代わりにこれを試してみてください。

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

t1; dr:チェックアウトsend_long_data()

これは非常に古い質問ですが、と正確にはでした。上記の答えを試して、実験に多くの時間を費やした後、私は最終的に質問と私が試していた方法で動作するものを見つけました。

(私が最初にスキップ)許可されたパケットサイズを超えるデータを参照するとき「B」PHP bind_param documentation種類の進め方についてのみ参照が間接的であるため、それは混乱を招く:

変数のデータサイズがmaxを超える場合。パケットサイズ (max_allowed_pa​​cketの)許可され、あなたは種類Bを指定して、パケット内のデータを送信するために mysqli_stmt_send_long_data()を使用する必要があります。

挿入を実行する前にバイナリタイプを送信する必要があります。私はこれをarticle from Oracle's websiteから見つけました。

:MySQLiをを使用してBLOBを保存するためのコードをブロブここ

を者蓄積

は、彼らはとても簡潔にそれを説明するので、私は最も関連性の高い部分を言い換えます

$stmt = $mysqli->prepare("INSERT INTO images (image) VALUES(?)") 
$null = NULL; //bolded 
$stmt->bind_param("b", $null); 

$stmt->send_long_data(0, file_get_contents("osaka.jpg")); //bolded 

$stmt->execute(); 

私は2つのコードを太字にしましたbind_param()は常に与えられたパラメータのための変数の参照を望んでいるので、

$ヌル変数

が必要とされている:インクが見て価値があります。この場合、 "b"( ブロブのような)パラメータ。したがって、 $ nullは、構文を有効にするための単なるダミーです。

私のBLOBパラメータを実際のデータで "満たす"必要があります。これはsend_long_data()によって行われます。 の最初のパラメータは、どのパラメータを使用してデータを関連付けるかを示します。 パラメータには0から始まる番号が付けられます。 のsend_long_data()の第2パラメータには、格納される実際のデータが格納されます。

send_long_data()を使用している間、あなたがこれを行う際に、BLOBは、MySQLののmax_allowed_pa​​cketより 大きなではありません

関連する問題