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

时间:2013-02-27 08:06:59

标签: php mysql bit

我有一个包含列bit(1)的表格和以下查询:SELECT my_bit FROM my_table

当我在echo页面上php结果时,该值显示为string(3) %qu 列上的位值是0还是1 < / strong>即可。这怎么可能?

以下问题解决了网页上echoing时的问题:SELECT CAST(my_bit AS UNSIGNED) AS my_bit FROM my_table

但是,上述两个查询都适用于命令行工具。那里没有string(3)

选择数据时一切正常,

之间没有区别
  1. SELECT * FROM my_table WHERE my_bit = 0
  2. SELECT * FROM my_table WHERE my_bit =(0)
  3. 使用命令行工具或网络界面php页面时。 (建议后者here。)Echoing必须使用CAST函数完成,但WHERE不受parentehis影响:返回正确的行。

    主要问题

    1. 如果bit值为0或1,返回的echoed类型值为string的{​​{1}}如何相同?
    2. 使用bit类型列插入/选择数据时是否有任何特殊问题需要考虑? (快速测试表明一切都按预期工作:0插入0和1插入1,但我可能会遗漏一些东西。)
    3. 我正在使用MAMP在本地测试:PHP 5.3.2和MySQL 5.1.44。命令行工具是指Sequel Pro(不是MAMP的PhpAdmin)。 bit(1)页面为Php,查询使用utf-8


      更新:代码

      SET NAMES 'utf8'

      查询选项1打印出来:

      CREATE TABLE `my_table` (
        `id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
        `my_bit` bit(1) NOT NULL,
        PRIMARY KEY (`id`,`lto_muu`)
      ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_swedish_ci;
      
      INSERT INTO `my_table` (`id`, `my_bit`) VALUES (null, 0), (null,1)
      
      //php page
      //query option 1
      SELECT `id`, `my_bit`  FROM `my_table`
      //query option 2
      SELECT `id`, CAST(`my_bit` AS UNSIGNED) AS `my_bit`  FROM `my_table`
      
      $mysqli = new mysqli("localhost", "root", "root","my_db");
      $q = "SELECT `id`, `my_bit`  FROM `my_table`";//returns 2 rows
      
      $r = $mysqli->query($q);
      
      while($row = mysqli_fetch_array($r,MYSQLI_ASSOC)){
      echo 'id: ' . $row['id'] . ' - bit: ' . $row['my_bit'] . '<br />';
      }
      

      查询选项2打印出来:

      id: 1 - bit: %qu
      id: 2 - bit: %qu
      

      更新2:Álvaro的代码

      id: 1 - bit: 0
      id: 2 - bit: 1
      

      使用 PHP 5.2.12 opt 1和2都打印:

      $conn = new mysqli('localhost', 'root', 'root','test');
      //$mysqli->set_charset('utf8');
      $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')");
      
      //opt 1
      $q = 'SELECT cast(my_bit as unsigned) as my_bit, my_multiple_bit FROM bit_test';
      //opt2 
      //$q = 'SELECT my_bit, my_multiple_bit FROM bit_test';
      $r = $conn->query($q);
      while($row = mysqli_fetch_array($r, MYSQLI_ASSOC)){
          echo bin2hex($row['my_bit']) . '<br />';
          echo bin2hex($row['my_multiple_bit']) . '<br />';
          var_dump($row);
          echo '<br /><br />';
      }
      

      使用 PHP 5.3.2 选项1打印:

      30
      07
      array(2) {
        ["my_bit"]=>
        string(1) "0"
        ["my_multiple_bit"]=>
        string(1) ""
      }
      31
      80
      array(2) {
        ["my_bit"]=>
        string(1) "1"
        ["my_multiple_bit"]=>
        string(1) "�"
      }
      

      并选择2:

      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"
      }
      

      PHP 5.3.2 alvays打印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" } 。这有什么意义吗?

2 个答案:

答案 0 :(得分:8)

简短回答

好的,这是我自己的问题的简短答案。如果您想确保bit(1)列被检索为整数,请在检索bit(1)值时使用以下查询:

$q = 'SELECT (my_bit + 0) AS my_bit, (my_multiple_bit + 0) AS my_multiple_bit FROM bit_test';

如果未使用“+ 0”,则bit(1)列的值将被视为binary stringThis is the moment when I say "RTM" to myself...

Something similar is found here through the magic of Google...

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

现在凌乱/冗长的答案(让我们使用Álvaro的代码)

让我们创建表并使用我的MAMP安装中可用的两个PHP版本的四个不同查询:5.3.2&amp; 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 />';
}

以下是不同查询的结果

我真正感兴趣的是普通输出和var_dump,但您也可以检查bin2hexbase16to10输出在查找数字是否有用时非常有用链接到相应的值:数字0,7,1和128(存储在表格的四个bit列中的值)。

q1 - 安全投注 - 输出在PHP 5.3.2&amp;中是相同的。 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: 128
bin2hex: 31
bin2hex: 313238
base16to10: 1
base16to10: 296
array(2) { ["my_bit"]=> string(1) "1" ["my_multiple_bit"]=> string(3) "128" }

q2 - 输出中的一些差异

bit(1)一起正常工作,但在my_multiple_bit输出中出现了一些错误。

PHP 5.2.12:
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) "�" } 
PHP 5.3.2
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" }

q3 - PHP 5.3.2&amp;中的输出相同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" }

q4 - 输出很奇怪

PHP 5.2.12适用于bit(1),但如果对使用的PHP版本或其行为有任何疑问,我不会使用此查询。

PHP 5.2.12
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) "�" } 
PHP 5.3.2
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" } 

最后的想法和自我注意

RTM,再次测试和测试。

同样很高兴知道这个%qu输出是否是独占的PHP 5.3.2错误。 (或者其他PHP版本会受到影响。)

所以,Álvaro的答案在使用CAST或从DB检索HEX值的意义上是正确的。 The manual显示了额外的“+0”方法,似乎从不同的PHP版本行为中消除了痛苦。因此,简短的回答是最重要的......

答案 1 :(得分:3)

以下是有关如何检索BIT列类型的完整示例:

<?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);
}

...打印:

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"
}

编辑#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版本按原样检索BIT列,因为原始二进制字符串(0x070x80是正确的数字7和{{1十进制)。

  • 在某些时候,添加了自动编码,并开始将128列作为小数检索。

  • OP使用的PHP版本可能在编码代码中有一个错误:BIT提醒我C printf修饰符(虽然我找不到它的确切定义)。

    < / LI>

鉴于行为不同,需要一种解决方法来确保连贯的输出:

  • %qu生成小数
  • CAST(my_bit AS UNSIGNED)生成十六进制数