PHP-使用准备好的语句在mysql中插入二进制数据
我必须使用 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
}
它不会给出错误,该行已插入,但标识符字段现在为空(不是 null,空)。
我知道我可以混合查询并输入字符串中连接的 id 和其他字段作为准备好的语句的绑定参数,但我只是想知道插入它的正确方法是什么,也许它会帮助某人未来。
I have to insert a row using php's mysql improved library to a table in mysql that has its primary key of type VARBINARY.
The contents of this field are a computed sha1 hash.
If I run the query the old way it works perfectly:
$mysqli->$query("INSERT INTO table (id, field1) VALUES (0x" . $id . ",'" . $field1 . "')");
But when I try to execute it as a prepared statement, I can't figure out how to do it. If
I perform the equivalent action:
if($stmt = $mysqli->prepare("INSERT INTO table (id, field1) VALUES (?, ?)")) {
$stmt->bind_param('ss', "0x".$id, $field1);
//execute statement
}
It throws an exception saying that the contents were too large for this field. And If I try to insert it as a BLOB field:
if($stmt = $mysqli->prepare("INSERT INTO table (id, field1) VALUES (?, ?)")) {
$stmt->bind_param('bs', $id, $field1);
//execute statement
}
It gives no error, the row is inserted, but the identifier field now is empty (not null, empty).
I know I can mix the query and input the id concatenated in the string and the other fields as bind parameters of the prepared statement, but i'm asking just to know what is the correct way to insert this and perhaps it will help somebody in the future.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
PHP 的 sha1 函数返回十六进制数字的字符串表示形式。
这意味着如果您将其打印到屏幕上,它将显示一个十六进制数字。但在内存中,它是一堆ASCII字符。
因此,取十六进制数
1A2F
。作为内存中的 ASCII,它是0x31413246
,而不是0x1A2F
MySQL 的普通接口将所有参数作为字符串发送。当使用普通接口时,MySQL会将ASCII字符串转换为二进制值。
新的准备好的语句方法将所有内容都以二进制形式发送。因此,“1A2F”的良好值现在将作为 0x31413246 发送并插入到列中。 - 来源:dev.mysql.com - 已准备相反
,请使用以下方法将十六进制字符串打包为二进制字符串:
然后将
$binId
传递给 MySQLi 准备好的语句而不是 $id。PHP's
sha1
function returns a string representation of a hex number.What that means is that if you print it to screen, it'll display a hex number. But in memory, it is an bunch of ASCII characters.
So, take the hex number
1A2F
. As ASCII in memory that would be0x31413246
, instead of0x1A2F
MySQL's normal interface sends all arguments as strings. When using the normal interface, MySQL will convert the ASCII string to a binary value.
The new prepared statement method sends everything as binary. So your nice value of "1A2F" will now be sent as 0x31413246 and inserted into the column. - source: dev.mysql.com - Prepared statements
Instead, convert your Hex string by packing it into a binary string using:
and then pass
$binId
to the MySQLi prepared statement instead of $id.试试这个:
try this instead:
tl;dr:查看 send_long_data()。
我知道这是一个非常古老的问题,但这正是我试图做但失败的事情。在尝试了上述答案并花了很多时间进行实验后,我终于找到了一些符合问题和我尝试的方法的东西。
这很令人困惑,因为有关如何继续处理 PHP 中的“b”类型的唯一参考是 bind_param 文档 是间接引用超过允许的数据包大小的数据(我最初跳过了):
事实证明,在执行插入之前,必须自行发送二进制类型。我从 Oracle 网站的文章中发现了这一点。
既然他们解释得如此简洁,我就解释一下最相关的部分:
tl;dr: check out send_long_data().
I know this is a very old question, but it was exactly what I was trying to do and failing at. After trying the above answers and spending much time experimenting, I finally found something that works the way the question and I were trying.
It's confusing because the only reference for how to proceed with "b" types in the PHP bind_param documentation is indirectly when referring to data exceeding the allowed packet size (which I initially skipped over):
It turns out that binary types must be sent by themselves before executing your insert. I found this out from an article from Oracle's website.
Since they explain it so succinctly, I'll just paraphrase the most relevant part: