|||||||||||||||||||||

なんぶ電子

- 更新: 

MariaDBでフラグを管理

MariaDBでビットを管理

MariaDBのビット型を使ってデータを格納をした際の覚書です。

列のタイプとビットの表記

MariaDBでビット処理をしたい場合に、それ用に用意されている列のタイプには「 BIT 」があります。

書くまでもないことですが、ロジック側で対応するするなら、「 INT 」や「 BIGINT 」、「 CHAR 」や「 VARCHAR 」も使えます。

ビットは bの接頭(ビットリテラル)の後に2進数文字列を続けることでコンソール上で利用可能です。

ただ、コンソール上でビット値を表示しようとすると文字化けしますので、通常は数値へキャストします。0と1の文字列にしたい場合は数値からBIN関数を通します。

/* bit型をコンソールに表示しようとすると文字化けします */
SELECT b'101' AS bit ;
+-----+
| bit |
+-----+
|  □ |
+-----+

/* bitの2進数値を10進数の値にして表示します */
SELECT CAST(b'101' AS UNSIGNED) bit;
+-----+
| bit |
+-----+
|   5 |
+-----+

/* 0と1の文字列にしたい場合は10進数の値からBIN関数を使います */
SELECT BIN(CAST(b'101' AS UNSIGNED)) bit;
+-----+
| bit |
+-----+
| 101 |
+-----+

BIT列の作成と挿入

列のタイプを BIT にする際は1~64の値を渡します。筆者の環境では何も設定しない場合や、0を指定した場合はサイズ1となりました。

マイナスの値や、65以上の値をセットするとエラーになります。

CREATE TABLE bit_test1(col1 BIT(32));
CREATE TABLE bit_test2(col1 BIT);

この列にデータを挿入したい場合、10進数の値かもしくはbの接頭を付けたバイナリ値を渡します。

INSERT INTO bit_test1 VALUES(128);
INSERT INTO bit_test1 VALUES(b'11001');

BIT列から行を選択

このようにして作成したBIT列の値を抽出するには論理演算を用います。

その際のいくつかの例示をします。

  • 2ビット目に1が立っている行を抽出
    SELECT BIN(CAST(col1 AS UNSIGNED)) bit FROM bit_test1 WHERE (col1 & b'10') = b'10';
  • 3ビット目に1が立っていない行を抽出
    SELECT BIN(CAST(col1 AS UNSIGNED)) bit FROM bit_test1 WHERE (col1 & b'100') = 0;
  • 1ビット目か3ビット目に1が立っている行を抽出
    SELECT BIN(CAST(col1 AS UNSIGNED)) bit FROM bit_test1 WHERE (col1 & b'101') != 0;

    | 演算子を用いることもできます。

    SELECT BIN(CAST(col1 AS UNSIGNED)) bit FROM bit_test1 WHERE (col1 & (b'1' | b'100')) != 0;
  • すべての行から4ビット目を除去
    UPDATE bit_test1 SET col1=col1 & ~b'1000' FROM bit_test1;

    ~は反転を意味して、指定した列のサイズ(ビット)で反転値を生成します。

ビットリテラルを付与していいる部分では、10進数化した値を用いることも可能です。

たとえば「 WHERE (col1 & b'101') 」は「 WHERE (col1 & 5) 」と置き換える事ができます。

INT型で定義された列も論理演算は使用可能

INT型(10進数)で列を定義している場合でもビット演算(論理演算)をすることができます。

たとえば、次のようなテーブルがあるとします。

CREATE TABLE bit_test3(col1 INT);

MariaDBでは値を自動的にキャストしてくれるので、BITで定義した列に10進数の値を挿入できるように、INTで定義した列にBITを挿入しても意図した値が入ります。

たとえば次のようにすると列には5が入ります。

INSERT INTO bit_test3 VALUES(b'101');
SELECT * FROM bit_test3;
+------+
| col1 |
+------+
|    5 |
+------+

条件においても同様で、10進数で書いてもビットリテラルをつけても処理が可能です。

SELECT BIN(col2) bit FROM bit_test3 WHERE (col1 & 2) = 2;

UPDATE bit_test3 SET col1=(col1 & ~b'1');

ビットリテラルがINT型の列に対してもでも意図したように機能するので、使うケースは少ないかもしれませんが、先ほどBIN関数で出力した2進数の文字列を10進数に変換する場合は、conv関数を用います。

SELECT CONV('10001',2,10) AS num;
+------+
| num  |
+------+
| 17   |
+------+

CONV関数は、第1引数に指定した文字列か数値を、第2引数で指定した基数から第3引数に指定した基数に変換します。つまりここでは'10001'という文字列を、2進数から10進数に変換しています。

SELECT文で取得する場合キャストしないといけないことを考えると、通常はビットを利用したい場合でもINTやBIGINTを用いた方が扱いやすいかもしれません。

BITを使うことで得られるメリットは、フラグ値であるという意図の表現や、データ量の削減(INTやBIGINTはひとつの列に対して32または64ビットを消費しますが、BITで定義した場合の領域は指定したサイズとなります)といったところでしょうか。

筆者紹介


自分の写真
がーふぁ、とか、ふぃんてっく、とか世の中すっかりハイテクになってしまいました。プログラムのコーディングに触れることもある筆者ですが、自分の作業は硯と筆で文字をかいているみたいな古臭いものだと思っています。 今やこんな風にブログを書くことすらAIにとって代わられそうなほど技術は進んでいます。 生活やビジネスでPCを活用しようとするとき、そんな第一線の技術と比べてしまうとやる気が失せてしまいがちですが、おいしいお惣菜をネットで注文できる時代でも、手作りの味はすたれていません。 提示されたもの(アプリ)に自分を合わせるのでなく、自分の活動にあったアプリを作る。それがPC活用の基本なんじゃなかと思います。 そんな意見に同調していただける方向けにLinuxのDebianOSをはじめとした基本無料のアプリの使い方を紹介できたらなと考えています。

広告