使用PHP7 MySQLi准备语句将BIT(M)列值插入MySQL5.7

时间:2017-10-02 18:39:20

标签: php mysql mysqli

当尝试使用MySQLi预处理语句将值插入BIT(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类型是整数,字符串,双精度和blob。我假设它正在发送'101010'(代码示例),101010(作为整数),'b'101010'''0b101010'等值;但是,需要的是b'101010'

出于速度和安全原因(其他领域),我必须使用预备语句。

我最初使用BIGINT,但是当大多数标志被设置时,似乎发生了舍入错误。

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

我的后备是很多TINYINT列或CHAR(64),但我希望更有效的存储。

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

修改

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

编辑2

通过phpMyAdmin插入并设置了所有1个标志也会提供0111111111111111111111111111111111111111111111111111111111111111,因此我配置此列的方式一定存在其他问题。我使用的是Ubuntu 16.04,服务器版本:5.7.19,PHP版本:7.0.22。

2 个答案:

答案 0 :(得分:0)

也许试试

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

但如果准备好的语句根本不支持位域,那就不会让我感到惊讶。

  

出于速度和安全原因(其他领域),我必须使用   准备好的陈述。

不,你没有。这将是安全的:

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

我向你保证,性能影响绝对是最小的,并以此为基准。

答案 1 :(得分:0)

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

您需要了解您真正使用的数据类型。您已经在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(例如, VALUES(? + 0)

要避免使用bindec(),可以在PHP中使用按位操作。该值将始终为整数。