4

bit(1)と次のクエリを含むテーブルがありますSELECT my_bit FROM my_table

ページechoの結果を見ると、値は列のビット値が0か1かとして表示されます。これはどのように可能ですか?phpstring(3) %qu

次のクエリechoingは、Webページでの問題を解決しました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)

コマンドラインツールまたはWebインターフェイスphpページを使用する場合。(後者はここで提案されています。)関数Echoingを使用して実行する必要がありますが、は括弧の影響を受けません。正しい行が返されます。CASTWHERE

主な質問

  1. 値が0であろうと1であろうと、返されるbit型の値がechoed同じになるのはなぜですか?stringbit
  2. bit(1)タイプ列を使用してデータを挿入/選択するときに考慮すべき特別な問題はありますか?(クイックテストでは、すべてが意図したとおりに機能することが示されています。0は0として挿入され、1は1として挿入されますが、何かが欠落している可能性があります。)

私はこれをMAMPでローカルにテストしています:PHP5.3.2とMySQL5.1.44。コマンドラインツールは、Sequel Pro(MAMPのPhpAdminではありません)を参照します。Phpページはutf-8あり、クエリはを使用しますSET NAMES 'utf8'


更新:コード

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 />';
}

クエリオプション1は次のように出力します。

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

クエリオプション2は次のように出力します。

id: 1 - bit: 0
id: 2 - bit: 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.2.12 opt 1と2の両方を使用すると、次のように出力されます。

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

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

PHP5.3.2alvaysは印刷し%quます。これは意味がありますか?

4

2 に答える 2

8

短い答え

OK、これが私自身の質問に対する短い答えと長い答えです。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 stringます。 これは私が自分自身に「RTM」と言う瞬間です...

グーグルの魔法を通してここに似たようなものが見つかります...

迅速な解決策に満足している場合は、今すぐ読むのをやめてください。

今、厄介な/長い答え(アルバロのコードを使用しましょう)

テーブルを作成し、MAMPインストールで利用可能な2つのPHPバージョン(5.3.2と5.2.12)で4つの異なるクエリを使用してみましょう。

$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 />';
}

さまざまなクエリの結果は次のとおりです

私が本当に興味を持っているのはプレーンな出力とですが、数値が対応する値(0、7、1、128)(格納されている値)にリンクしているかどうかを調べるときに、出力が役立つvar_dumpことも確認できます。表の4列に)。bin2hexbase16to10bit

q1 –安全な賭け–出力はPHP5.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: 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) "�&quot; } 
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 –出力はPHP5.3.2と5.2.12で同じです

これも安全なクエリです。取得した16進数を10進数に変換することを忘れないでください。

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) "�&quot; } 
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また、この出力がPHP5.3.2の排他的なバグであるかどうかを確認しておくと便利です。(または他のどのPHPバージョンが影響を受けますか。)

したがって、アルバロの答えは、DBから値を使用CASTまたは取得するという意味で正しいです。マニュアルは、さまざまなPHPバージョンの動作から苦痛を取り除くように見える追加の「+0」メソッドを明らかにしました。したがって、短い答えは一番上にあります...HEX

于 2013-02-28T10:40:47.147 に答える
4

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は正しい数値で712810 進数です)。

  • ある時点で、自動エンコードが追加され、BIT列が 10 進数として取得されるようになりました。

  • OP で使用される PHP リリースには、おそらくエンコード コードにバグが%quあります。C の printf 修飾子を思い出させます (ただし、正確な定義は見つかりませんでした)。

動作が異なるため、一貫した出力を確保するには回避策が必要です。

  • CAST(my_bit AS UNSIGNED)10進数を生成する
  • HEX(my_bit)16進数を生成する
于 2013-02-27T09:07:32.287 に答える