使用PHP7 MySQLI准备的语句将位(M)列值插入MySQL5.7



尝试使用mysqli准备的语句将值插入一些(64)列时,我将收到错误(执行):

数据太长对于第1行'bits64'列

这是我的代码:

if ($Segments[0] == 'yes') {$bitmask = '1';}else{$bitmask = '0';}
if ($Segments[1] == 'yes') {$bitmask = $bitmask.'1';}else{$bitmask = $bitmask.'0';}
...
if ($Segments[63] == 'yes') {$bitmask = $bitmask.'1';}else{$bitmask = $bitmask.'0';}
$Upload = $conn->prepare("INSERT INTO `testtable` (`bits64`) VALUES (?)");
$Upload->bind_param("s", $bitmask);
$Upload->execute();

代码提供64个字符串。如果我使用phpMyAdmin插入相同的输出,则可以成功地工作,并且看起来像这样:

INSERT INTO `testtable` (`bits64`) VALUES (b'0000000000000000000000000000000000000000000000000000000000000000');
INSERT INTO `testtable` (`bits64`) VALUES (b'1111111111111111111111111111111111111111111111111111111111111111');

唯一显示任何"成功"(*不是真正)的东西是将绑定类型更改为整数。但是看来它被视为应该转换为二进制的整数,因为它在设置为 1的位标志时给出了相同的错误。

我尝试过的其他事情包括格式化$bitmask为:

$bitmask = "b'".$bitmask."'";
$bitmask = "0b".$bitmask;
// And others 

据我所知,唯一的bind_param类型是整数,字符串,双重和斑点。我认为它是在谨慎地发送诸如'101010'(代码示例),101010(AS INTEGER),'b'101010'''0b101010'之类的值;但是,需要的是b'101010'

出于速度和安全原因(其他字段),我必须使用准备好的语句。

我最初使用bigint为此,但似乎在设置大多数标志时发生了舍入错误。

我认为我已禁用MySQL严格模式。

我的后备是很多Tinyint列或字符(64),但我更喜欢更有效的存储。

本网站上有一些相关的问题,但是大多数与单个位字段有关,其中整数0或1与单个位更容易相关。我应该最感激任何建议或解决方案。

编辑

我意识到我没有完全空白的SQL模式。一旦SQL模式是一个空字符串,就没有错误,但是无论我尝试什么,我都会得到0111111111111111111111111111111111111111111111111111111111111111

编辑2

通过PhpMyAdmin插入所有1个标志集也会给出0111111111111111111111111111111111111111111111111111111111111111,因此我配置了此列的方式必须有其他问题。我正在使用Ubuntu 16.04,服务器版本:5.7.19,PHP版本:7.0.22。

这是绑定类型很重要的示例之一...但在您的情况下并没有真正有所帮助。

您需要了解您真正使用的数据类型。您已经在PHP中创建了一串数字。这不是二进制号码!这只是一个字符串。php可以杂乱无章并施放它,但是您需要用PHP明确说明您想要的是一个数字,而不是字符串。

一种方法是:

$bitmask = bindec($bitmask); // convert binary string to decimal number
$Upload = $conn->prepare("INSERT INTO `testtable` (`bits64`) VALUES (?)");
$Upload->bind_param("i", $bitmask); // bind as integer
$Upload->execute();

如果要避免用作整数绑定,则可以使用VALUES(CAST(? AS UNSIGNED))或仅通过添加0例如0,例如。VALUES(? + 0)

要避免使用bindec(),您可以在PHP中使用位置操作。然后,该值将始终是整数。

也许尝试

$Upload = $conn->prepare("INSERT INTO `testtable` (`bits64`) VALUES (b?)");

,如果准备好的陈述并不能真正支持Bitfields,这不会让我感到惊讶。

出于速度和安全原因(其他字段),我必须使用 准备的语句。

不,你不。这同样是安全的:

if(strlen(rtrim($bitmask,'01'))!==0){throw new RuntimeException('illegal characters found in bitmask!');}
$conn->query('INSERT INTO `testtable` (`bits64`) VALUES (b''.$bitmask.'')');

我向您保证,性能影响绝对是最小的,基准的。

最新更新