当尝试使用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 Mode为空字符串,就不会出现错误,但是无论尝试如何,我都会得到0111111111111111111111111111111111111111111111111111111111111111

编辑2

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

最佳答案

也许尝试

$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.'\')');


并且我向您保证,对性能的影响将是最小的,对其进行基准测试。

10-05 21:09
查看更多