0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

MySQL 5.6.14で16進数化されたASCIIデータを取り扱う

Last updated at Posted at 2018-10-12

MySQLで16進数のASCIIデータを取り扱う

経緯

SNMPでデータ取得をしてMySQLにぶち込むスクリプトを組んでいたところ、HEX型で返ってくるデータがあったのでとりあえずそのままぶち込んだ。
そのあと、データを取り出してASCII文字列に変換するのにちょっと困った話。

やったこと

mysql> CREATE TABLE test (hexdata varchar(512) DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.21 sec)
mysql> insert into test values '0x544553547465737421'; #TESTtest!
Query OK, 1 row affected (0.00 sec)
mysql> SELECT hexdata FROM test;
+----------------------+
| hexdata              |
+----------------------+
| 0x544553547465737421 |
+----------------------+
1 row in set (0.00 sec)
mysql> SELECT unhex(hexdata) FROM test;
+----------------+
| unhex(hexdata) |
+----------------+
| NULL           |
+----------------+
1 row in set (0.00 sec)
->unhex効かない?
mysql> SELECT unhex(substring(hexdata,3,length(hexdata))) FROM test;
+---------------------------------------------+
| unhex(substring(hexdata,3,length(hexdata))) |
+---------------------------------------------+
| TESTtest!                                   |
+---------------------------------------------+
1 row in set (0.00 sec)
->unhexは0-9A-Fで書かれたデータしか変換できないので、頭に'0x'があった場合は削除する必要ある。

以上。

ダメだったこと

16進法をASCII化するには
SELECT x'TESTtest!'
みたいに書いてあることがあるんだけど、x構文ってテーブルデータに対して使えない気がする。

mysql> SELECT x'0x544553547465737421' ;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'x'0x544553547465737421'' at line 1

mysql> SELECT x'544553547465737421' ;
+-----------------------+
| x'544553547465737421' |
+-----------------------+
| TESTtest!             |
+-----------------------+
1 row in set (0.00 sec)
/* x構文でも頭の'0x'は外す必要ある。
   じゃあ、テーブルのレコードに対してx構文ってどうやって使う? */

mysql> SELECT x hexdata FROM test;
ERROR 1054 (42S22): Unknown column 'x' in 'field list'
/* 行と解釈されてError.当たり前 */

mysql> SELECT x(substring(hexdata,3,length(hexdata))) FROM test;
+-----------------------------------------+
| x(substring(hexdata,3,length(hexdata))) |
+-----------------------------------------+
|                                    NULL |
+-----------------------------------------+
1 row in set (0.00 sec)
/* 出てこない。 */

じゃあ、HEXデータでフィルタは?

HEXデータそのままでは使いづらいため、やっぱり文字列変換後にフィルタを書きたい。
HEXデータの場合、ある程度の制御コードも入ってくることが想定される(ていうか、実際に混ざってきてた)。
なので、まずはNULL(0x00)が入っていることを想定。

mysql> TRUNCATE test;
Query OK, 0 rows affected (0.34 sec)

mysql> insert into test values ('0x544553547465737421'),('0x00544553547465737421'),('0x544553547465737421005454'),('0x00544553547465737421005353');
Query OK, 4 rows affected (0.00 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> SELECT hexdata,unhex(substring(hexdata,3,length(hexdata))) hex2ascii FROM test ;
+------------------------------+---------------+
| hexdata                      | hex2ascii     |
+------------------------------+---------------+
| 0x544553547465737421         | TESTtest!     |
| 0x00544553547465737421       |  TESTtest!    |
| 0x544553547465737421005454   | TESTtest! TT  |
| 0x00544553547465737421005353 |  TESTtest! SS |
+------------------------------+---------------+
4 rows in set (0.00 sec)

/* まずはLikeで抽出 */
mysql> SELECT hexdata,unhex(substring(hexdata,3,length(hexdata))) hex2ascii FROM test WHERE unhex(substring(hexdata,3,length(hexdata))) like 'TEST%';
+----------------------------+--------------+
| hexdata                    | hex2ascii    |
+----------------------------+--------------+
| 0x544553547465737421       | TESTtest!    |
| 0x544553547465737421005454 | TESTtest! TT |
+----------------------------+--------------+
2 rows in set (0.00 sec)
->頭にNULL文字が入っている行は抽出できない。一応データ扱いらしい。

mysql> SELECT hexdata,unhex(substring(hexdata,3,length(hexdata))) hex2ascii FROM test WHERE unhex(substring(hexdata,3,length(hexdata))) like '%TEST%';
+------------------------------+---------------+
| hexdata                      | hex2ascii     |
+------------------------------+---------------+
| 0x544553547465737421         | TESTtest!     |
| 0x00544553547465737421       |  TESTtest!    |
| 0x544553547465737421005454   | TESTtest! TT  |
| 0x00544553547465737421005353 |  TESTtest! SS |
+------------------------------+---------------+
4 rows in set (0.00 sec)
->出てきた。

/* LikeはわかったのでRegexpで抽出。 */
mysql> SELECT hexdata,unhex(substring(hexdata,3,length(hexdata))) hex2ascii FROM test WHERE unhex(substring(hexdata,3,length(hexdata))) regexp 'TEST';
+----------------------------+--------------+
| hexdata                    | hex2ascii    |
+----------------------------+--------------+
| 0x544553547465737421       | TESTtest!    |
| 0x544553547465737421005454 | TESTtest! TT |
+----------------------------+--------------+
2 rows in set (0.00 sec)
->????

mysql> SELECT hexdata,unhex(substring(hexdata,3,length(hexdata))) hex2ascii FROM test WHERE unhex(substring(hexdata,3,length(hexdata))) regexp 'TT';
Empty set (0.00 sec)
->?????!!!!

unhexしたデータでフィルタかける場合、LIKEはある程度想定通りの動作をするが、REGEXPはnulll(0x00)が入っているとその後ろのデータは抽出条件として使えないっぽい。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?