Php MySQL选择位(1)显示为字符串(3)

Php MySQL选择位(1)显示为字符串(3),php,mysql,bit,Php,Mysql,Bit,我有一个列为bit1的表和以下查询:从my_表中选择my_位 当我在php页面上回显结果时,无论列上的位值是0还是1,该值都显示为string3%qu。这怎么可能 以下查询解决了在网页上回送时的问题:从my_表中选择CASTmy_位作为未签名的my_位 但是,上述两个查询都在命令行工具上工作。没有 此外,在选择数据时,一切都正常工作,两者之间没有区别 从my_表中选择*,其中my_位=0 从my_表中选择*,其中my_位=0 使用命令行工具或web界面php页面时。建议采用后者。回送必须使用CA

我有一个列为bit1的表和以下查询:从my_表中选择my_位

当我在php页面上回显结果时,无论列上的位值是0还是1,该值都显示为string3%qu。这怎么可能

以下查询解决了在网页上回送时的问题:从my_表中选择CASTmy_位作为未签名的my_位

但是,上述两个查询都在命令行工具上工作。没有

此外,在选择数据时,一切都正常工作,两者之间没有区别

从my_表中选择*,其中my_位=0 从my_表中选择*,其中my_位=0 使用命令行工具或web界面php页面时。建议采用后者。回送必须使用CAST函数完成,但WHERE不受parenthis的影响:返回正确的行

主要问题 为什么无论位值是0还是1,返回的位类型值都作为相同的字符串回显? 在使用bit1类型列插入/选择数据时,是否应考虑任何特殊问题?快速测试表明一切都按预期进行:0作为0插入,1作为1插入,但我可能遗漏了一些内容。 我正在本地用MAMP:php5.3.2和MySQL 5.1.44测试这一点。命令行工具指的是Sequel Pro,而不是MAMP的PhpAdmin。Php页面是utf-8,查询使用集合名称“utf8”

更新:代码 查询选项2打印出:

id: 1 - bit: %qu
id: 2 - bit: %qu
id: 1 - bit: 0
id: 2 - bit: 1
更新2:阿尔瓦罗的代码 使用PHP 5.3.2 opt 1打印:

30
257175
array(2) {
  ["my_bit"]=>
  string(1) "0"
  ["my_multiple_bit"]=>
  string(3) "%qu"
}
31
257175
array(2) {
  ["my_bit"]=>
  string(1) "1"
  ["my_multiple_bit"]=>
  string(3) "%qu"
}
和选择2:

257175
257175
array(2) {
  ["my_bit"]=>
  string(3) "%qu"
  ["my_multiple_bit"]=>
  string(3) "%qu"
}
257175
257175
array(2) {
  ["my_bit"]=>
  string(3) "%qu"
  ["my_multiple_bit"]=>
  string(3) "%qu"
}

PHP 5.3.2 Always打印%qu。这有意义吗?

下面是一个关于如何检索位列类型的完整示例:

<?php

$conn = new PDO('mysql:host=test;dbname=test', 'test', 'test');
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$conn->query('DROP TABLE IF EXISTS bit_test');
$conn->query('CREATE TABLE bit_test (
    my_bit BIT(1) NULL,
    my_multiple_bit BIT(8) NULL
)');
$conn->query("INSERT INTO bit_test (my_bit, my_multiple_bit) VALUES (b'0', b'111')");
$conn->query("INSERT INTO bit_test (my_bit, my_multiple_bit) VALUES (b'1', b'10000000')");

$res = $conn->query('SELECT my_bit, my_multiple_bit FROM test');
while($row = $res->fetch(PDO::FETCH_ASSOC)){
    var_dump($row);
}
编辑1:

以下是我以前的代码,适用于mysqli:

<?php

$conn = new mysqli('localhost', 'test', 'test','test');

$conn->query('DROP TABLE IF EXISTS bit_test');
$conn->query('CREATE TABLE bit_test (
    my_bit BIT(1) NULL,
    my_multiple_bit BIT(8) NULL
)');
$conn->query("INSERT INTO bit_test (my_bit, my_multiple_bit) VALUES (b'0', b'111')");
$conn->query("INSERT INTO bit_test (my_bit, my_multiple_bit) VALUES (b'1', b'10000000')");

$res = $conn->query('SELECT my_bit, my_multiple_bit FROM test');
#while($row = mysqli_fetch_array($res, MYSQLI_ASSOC)){
while($row = $res->fetch_array(MYSQLI_ASSOC)){
    var_dump($row);
}
我得到了一个附加的数组项,所有值都设置为NULL。我对mysqli不熟悉,所以这可能是我的错,但输出在其他方面是相同的。我已经在PHP/5.3.0和PHP/5.4.5中对其进行了测试

我建议您逐字地尝试我的代码,并验证您是否仍然得到%qu或其他奇怪的东西。我有一种强烈的感觉,这种%qu字符串可能从其他地方泄漏

编辑2:

从其他信息中,我认为我们可以得出以下结论:

早期的PHP版本按原样检索位列,因为原始二进制字符串0x07和0x80是正确的数字,十进制为7和128

在某个时刻,添加了自动编码,开始以小数形式检索位列

OP使用的PHP版本可能在编码代码中有一个错误:%qu让我想起了C printf修饰符,尽管我找不到它的确切定义

鉴于不同的行为,需要一种变通方法来确保一致的输出:

CASTmy_位为无符号以生成十进制数 HEXmy_位生成十六进制数 简短回答 好的,以下是我自己问题的简短答案。如果要确保将位1列作为整数检索,请在检索位1值时使用以下查询:

$q='从位测试中选择my_位+0作为my_位,my_多重位+0作为my_多重位'

如果未使用+0,则位1列的值将被视为二进制字符串。

如果您对快速解决方案感到满意,请立即停止阅读

现在,让我们使用阿尔瓦罗的代码来给出一个混乱/冗长的答案 让我们创建这个表,并使用四个不同的查询,在我的MAMP安装中提供了两个PHP版本:5.3.2和5.2.12

$conn = new mysqli('localhost', 'root', 'root','my_db');

$conn->query('DROP TABLE IF EXISTS bit_test');
$conn->query('CREATE TABLE bit_test (
    my_bit BIT(1) NULL,
    my_multiple_bit BIT(8) NULL
)');

$conn->query("INSERT INTO bit_test (my_bit, my_multiple_bit) VALUES (b'0', b'111')");
$conn->query("INSERT INTO bit_test (my_bit, my_multiple_bit) VALUES (b'1', b'10000000')");

//q1
$q = 'SELECT (my_bit + 0) AS my_bit, (my_multiple_bit + 0) AS my_multiple_bit FROM bit_test';
//q2
//$q = 'SELECT cast(my_bit as unsigned) as my_bit, my_multiple_bit FROM bit_test';
//q3
//$q = 'SELECT HEX(my_bit) AS my_bit , HEX(my_multiple_bit) AS my_multiple_bit FROM bit_test';
//q4
//$q = 'SELECT my_bit, my_multiple_bit FROM bit_test';

$r = $conn->query($q);

//let's echo a few options
//plain gives unaltered result
//bin2hex gives hexadecimal number of an ASCII string (since) the values are treated as strings
//base16to10 gives decimal representation of hexadecimal value
//yes, the two functions are contradictionary (dependable of the query in use)
//but I'll echo their result anyway
while($row = mysqli_fetch_array($r, MYSQLI_ASSOC)){
  echo 'plain: ' . $row['my_bit'] . '<br />';
  echo 'plain: ' . $row['my_multiple_bit'] . '<br />';
  echo 'bin2hex: ' . bin2hex($row['my_bit']) . '<br />';
  echo 'bin2hex: ' . bin2hex($row['my_multiple_bit']) . '<br />';
  echo 'base16to10: ' . base_convert($row['my_bit'],16,10) . '<br />';
  echo 'base16to10: ' . base_convert($row['my_multiple_bit'],16,10) . '<br />';
  var_dump($row);
  echo '<br /><br />';
}
q2–产出方面的一些差异 使用bit1可以很好地工作,但在我的\u多\u位输出中出现了一些问题

PHP 5.2.12: PHP 5.3.2 q3–PHP 5.3.2和5.2.12中的输出相同 这也是一个可以使用的安全查询。请记住将检索到的十六进制数转换为十进制数

plain: 0
plain: 7
bin2hex: 30
bin2hex: 37
base16to10: 0
base16to10: 7
array(2) { ["my_bit"]=> string(1) "0" ["my_multiple_bit"]=> string(1) "7" }

plain: 1
plain: 80
bin2hex: 31
bin2hex: 3830
base16to10: 1
base16to10: 128
array(2) { ["my_bit"]=> string(1) "1" ["my_multiple_bit"]=> string(2) "80" }
第四季度——产出相当奇怪 PHP5.2.12可以很好地处理bit1,但如果对使用中的PHP版本或其行为有任何疑问,我不会使用此查询

PHP 5.2.12 PHP 5.3.2 最后的想法和自我说明 RTM,一次又一次的测试

另外,如果能确定这个%qu输出是否是PHP5.3.2独有的bug,那就太好了。或者其他哪些PHP版本受到影响


因此,阿尔瓦罗的答案是正确的,因为他使用强制转换或从DB中检索十六进制值。显示了额外的+0方法,它似乎消除了不同PHP版本行为带来的痛苦。因此,简短的答案就在最上面…

我无法复制它。我总是得到原始二进制位或二进制数的十进制表示,这取决于我的测试方式。我认为这个问题在没有看到你的代码的情况下是无法解决的。恐怕我仍然无法复制它。我在两个查询中都得到了id:1-bit:0id:2-bit:1。@alvaro我在PHP5.3.2中得到了MAMP。我尝试了MAMP中提供的另一种选择:PHP5.2.13。尽管var_dump显示[my_bit]=>string1,但使用查询选项2不会输出任何内容。为什么空字符串的长度为1。这个问题似乎只与PHP版本有关。或者有其他解释吗?string1表示有一个字节。它不需要是p
可打印字符。如果您没有十六进制编辑器,可以使用它进行检查。您的代码是否使用绑定变量?添加了代码,抱歉,花了一些时间。我在我的页面和singleton类上使用ajax调用来连接到DB,但是示例代码重新创建了这个问题。请让我知道是否需要任何其他信息,如果您无法使用示例代码重新创建问题。+1昨天为您提供帮助。我挖得更深一点,补充了我自己的答案。如果没有人提供更好的解释或证明我们中的任何一方是错的,我会在几天后接受你或我的回答。您的十六进制/十进制视图帮助很大。谢谢你的帮助。接受了这个答案,因为它帮助我理解了最初的问题。这个答案也有一个有效的解决方案。一定要检查我的答案也为其他工作解决方案。
array(2) {
  ["my_bit"]=>
  string(1) "0"
  ["my_multiple_bit"]=>
  string(1) "7"
}
array(2) {
  ["my_bit"]=>
  string(1) "1"
  ["my_multiple_bit"]=>
  string(3) "128"
}
<?php

$conn = new mysqli('localhost', 'test', 'test','test');

$conn->query('DROP TABLE IF EXISTS bit_test');
$conn->query('CREATE TABLE bit_test (
    my_bit BIT(1) NULL,
    my_multiple_bit BIT(8) NULL
)');
$conn->query("INSERT INTO bit_test (my_bit, my_multiple_bit) VALUES (b'0', b'111')");
$conn->query("INSERT INTO bit_test (my_bit, my_multiple_bit) VALUES (b'1', b'10000000')");

$res = $conn->query('SELECT my_bit, my_multiple_bit FROM test');
#while($row = mysqli_fetch_array($res, MYSQLI_ASSOC)){
while($row = $res->fetch_array(MYSQLI_ASSOC)){
    var_dump($row);
}
$conn = new mysqli('localhost', 'root', 'root','my_db');

$conn->query('DROP TABLE IF EXISTS bit_test');
$conn->query('CREATE TABLE bit_test (
    my_bit BIT(1) NULL,
    my_multiple_bit BIT(8) NULL
)');

$conn->query("INSERT INTO bit_test (my_bit, my_multiple_bit) VALUES (b'0', b'111')");
$conn->query("INSERT INTO bit_test (my_bit, my_multiple_bit) VALUES (b'1', b'10000000')");

//q1
$q = 'SELECT (my_bit + 0) AS my_bit, (my_multiple_bit + 0) AS my_multiple_bit FROM bit_test';
//q2
//$q = 'SELECT cast(my_bit as unsigned) as my_bit, my_multiple_bit FROM bit_test';
//q3
//$q = 'SELECT HEX(my_bit) AS my_bit , HEX(my_multiple_bit) AS my_multiple_bit FROM bit_test';
//q4
//$q = 'SELECT my_bit, my_multiple_bit FROM bit_test';

$r = $conn->query($q);

//let's echo a few options
//plain gives unaltered result
//bin2hex gives hexadecimal number of an ASCII string (since) the values are treated as strings
//base16to10 gives decimal representation of hexadecimal value
//yes, the two functions are contradictionary (dependable of the query in use)
//but I'll echo their result anyway
while($row = mysqli_fetch_array($r, MYSQLI_ASSOC)){
  echo 'plain: ' . $row['my_bit'] . '<br />';
  echo 'plain: ' . $row['my_multiple_bit'] . '<br />';
  echo 'bin2hex: ' . bin2hex($row['my_bit']) . '<br />';
  echo 'bin2hex: ' . bin2hex($row['my_multiple_bit']) . '<br />';
  echo 'base16to10: ' . base_convert($row['my_bit'],16,10) . '<br />';
  echo 'base16to10: ' . base_convert($row['my_multiple_bit'],16,10) . '<br />';
  var_dump($row);
  echo '<br /><br />';
}
plain: 0
plain: 7
bin2hex: 30
bin2hex: 37
base16to10: 0
base16to10: 7
array(2) { ["my_bit"]=> string(1) "0" ["my_multiple_bit"]=> string(1) "7" }

plain: 1
plain: 128
bin2hex: 31
bin2hex: 313238
base16to10: 1
base16to10: 296
array(2) { ["my_bit"]=> string(1) "1" ["my_multiple_bit"]=> string(3) "128" }
plain: 0
plain: 
bin2hex: 30
bin2hex: 07
base16to10: 0
base16to10: 0
array(2) { ["my_bit"]=> string(1) "0" ["my_multiple_bit"]=> string(1) "" }

plain: 1
plain: �
bin2hex: 31
bin2hex: 80
base16to10: 1
base16to10: 0
array(2) { ["my_bit"]=> string(1) "1" ["my_multiple_bit"]=> string(1) "�" } 
plain: 0
plain: %qu
bin2hex: 30
bin2hex: 257175
base16to10: 0
base16to10: 0
array(2) { ["my_bit"]=> string(1) "0" ["my_multiple_bit"]=> string(3) "%qu" }

plain: 1
plain: %qu
bin2hex: 31
bin2hex: 257175
base16to10: 1
base16to10: 0
array(2) { ["my_bit"]=> string(1) "1" ["my_multiple_bit"]=> string(3) "%qu" }
plain: 0
plain: 7
bin2hex: 30
bin2hex: 37
base16to10: 0
base16to10: 7
array(2) { ["my_bit"]=> string(1) "0" ["my_multiple_bit"]=> string(1) "7" }

plain: 1
plain: 80
bin2hex: 31
bin2hex: 3830
base16to10: 1
base16to10: 128
array(2) { ["my_bit"]=> string(1) "1" ["my_multiple_bit"]=> string(2) "80" }
plain:
plain: 
bin2hex: 00
bin2hex: 07
base16to10: 0
base16to10: 0
array(2) { ["my_bit"]=> string(1) "" ["my_multiple_bit"]=> string(1) "" }

plain: 
plain: �
bin2hex: 01
bin2hex: 80
base16to10: 0
base16to10: 0
array(2) { ["my_bit"]=> string(1) "" ["my_multiple_bit"]=> string(1) "�" } 
plain: %qu
plain: %qu
bin2hex: 257175
bin2hex: 257175
base16to10: 0
base16to10: 0
array(2) { ["my_bit"]=> string(3) "%qu" ["my_multiple_bit"]=> string(3) "%qu" }

plain: %qu
plain: %qu
bin2hex: 257175
bin2hex: 257175
base16to10: 0
base16to10: 0
array(2) { ["my_bit"]=> string(3) "%qu" ["my_multiple_bit"]=> string(3) "%qu" }