簡體   English   中英

PHP-使用預准備語句在mysql中插入二進制數據

[英]PHP- inserting binary data in mysql using prepared statements

我必須使用php的mysql改進庫將一行插入到mysql中具有類型為VARBINARY的主鍵的表中。 該字段的內容是計算的sha1哈希。

如果我以舊的方式運行查詢它完美地工作:

$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
}

它沒有給出錯誤,插入了行,但標識符字段現在為空(不為空,為空)。

我知道我可以混合查詢並輸入字符串中連接的id和其他字段作為預准備語句的綁定參數,但我只是想知道插入這個的正確方法是什么,也許它會幫助某些人未來。

PHP的sha1函數返回十六進制數字的字符串表示形式。

這意味着如果你將它打印到屏幕上,它將顯示一個十六進制數字。 但在內存中,它是一堆ASCII字符。

所以,取十六進制數1A2F 作為內存中的ASCII,將是0x31413246 ,而不是0x1A2F

MySQL的普通接口將所有參數作為字符串發送。 使用普通接口時,MySQL會將ASCII字符串轉換為二進制值。

新的預處理語句方法將所有內容都以二進制形 因此,“1A2F”的漂亮值現在將作為0x31413246發送並插入到列中。 - source:dev.mysql.com - 准備好的聲明

相反,通過使用以下方法將Hex字符串打包成二進制字符串來轉換它:

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

然后將$binId傳遞給MySQLi預處理語句而不是$ id。

試試這個:

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

tl; dr:看看send_long_data()

我知道這是一個非常古老的問題,但這正是我試圖做的事情並且失敗了。 在嘗試上述答案並花費大量時間進行實驗之后,我終於發現了一些與我正在嘗試的問題一致的方式。

這令人困惑,因為在引用超出允許數據包大小的數據時(我最初跳過的),間接引用如何在PHP bind_param文檔中繼續使用“b”類型是唯一的:

如果變量的數據大小超過最大值。 允許的數據包大小(max_allowed_pa​​cket),您必須在類型中指定b並使用mysqli_stmt_send_long_data()以數據包的形式發送數據。

事實證明,在執行插入之前必須自己發送二進制類型。 從Oracle網站一篇文章中發現了這一點。

由於他們如此簡潔地解釋,我只想解釋最相關的部分:

存儲blob

這是使用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();

我加粗了兩段代碼,我認為值得關注:

$ null變量是必需的,因為bind_param()總是需要給定參數的變量引用。 在這種情況下,“b”(如blob中)參數。 所以$ null只是一個虛擬,以使語法工作。

在下一步中,我需要用實際數據“填充”我的blob參數。 這是由send_long_data()完成的。 此方法的第一個參數指示將數據與哪個參數相關聯。 參數從0開始編號.send_long_data()的第二個參數包含要存儲的實際數據。

使用send_long_data()時 ,請確保blob不大於MySQL的max_allowed_pa​​cket

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM