MySQL では @ で始まるユーザ定義変数を使うことができます。
mysql> SET @v1=123, @s1="ABC"; Query OK, 0 rows affected (0.00 sec)
こんなふうに定義すると、SELECTなどで使うことができます。
ここで、上で定義した2つの変数と、未定義の変数をSELECT文で見てみると:
mysql> SELECT @v1, @s1, @t1; +------+------+------------+ | @v1 | @s1 | @t1 | +------+------+------------+ | 123 | ABC | 0x | +------+------+------------+
上で値をセットした v1, s1 は、それぞれセットしたとおりの値が表示されていますが、未定義の @t1 には "0x" と表示されてしまいました。
値が NULL だとそうなるのか?
mysql> SET @s1=NULL; mysql> SELECT @v1, @s1, @t1; +------+------+------------+ | @v1 | @s1 | @t1 | +------+------+------------+ | 123 | NULL | 0x | +------+------+------------+
そうではないようです。
ブランクなら?
mysql> SET @v1=""; mysql> SELECT @v1, @s1, @t1; +------+------+------------+ | @v1 | @s1 | @t1 | +------+------+------------+ | | NULL | 0x | +------+------+------------+
セットしたとおりにブランクが出力されます。
じゃぁ未定義の値に書き換えてしまえば再現するのでは?と試してみると
mysql> set @v1=@xxx; mysql> SELECT @v1, @s1, @t1; +------+------+------------+ | @v1 | @s1 | @t1 | +------+------+------------+ | NULL | NULL | 0x | +------+------+------------+
NULL になってしまう。
ちなみに、未定義の変数に未定義の値を代入すると、NULLにはならず、未定義的な値が出力されます。
mysql> SET @u1=@u2; mysql> SELECT @u1, @u2; +------------+------------+ | @u1 | @u2 | +------------+------------+ | 0x | 0x | +------------+------------+
最初の値に戻って、HEXを取ってみると、未定義のところは、やっぱり未定義である模様(=何か不可視な値が入っているわけではない)。
mysql> SET @v1=123, @s1="ABC"; mysql> SELECT HEX(@v1), HEX(@s1), HEX(@t1); +----------+----------+----------+ | HEX(@v1) | HEX(@s1) | HEX(@t1) | +----------+----------+----------+ | 7B | 414243 | NULL | +----------+----------+----------+
ちなみにこの事象、
MySQL 8.0.20:
mysql> SELECT @v1, @s1, @t1; +------+------+------------+ | @v1 | @s1 | @t1 | +------+------+------------+ | 123 | ABC | 0x | +------+------+------------+
MySQL 8.0.19:
mysql> SELECT @v1, @s1, @t1; +------+------+------------+ | @v1 | @s1 | @t1 | +------+------+------------+ | 123 | ABC | 0x | +------+------+------------+
MySQL 8.0.17:
mysql> SELECT @v1, @s1, @t1; +------+------+------------+ | @v1 | @s1 | @t1 | +------+------+------------+ | 123 | ABC | NULL | +------+------+------------+
8.0.18 は、ちょうど手元に使える環境がなかったので未確認。
8.0.18または19になったときに挙動が変わったようですね。
と、ここで今回も救世主登場。 いつもいつも、皆さんありがとうございます。
見え方的には前にも話題になった--binary_as_hexのように見えますね!
— yoku0825 (@yoku0825) 2020年5月1日
ということで、「発生しなかった」MySQL 8.0.17 の mysqlクライアント起動オプションを変更して、リトライ!
MySQL 8.0.17:
$ mysql -uroot -p --binary-as-hex : (略) mysql> select @n1; +------------+ | @n1 | +------------+ | 0x | +------------+
なったぁ!!!!
結論:
『mysqlクライアントで、binary_as_hex の時には、未定義のユーザ変数は "0x" と出力される』
・・・・という仕様、、、、、と言っていいのかな。言いたくないな(笑)。
少なくとも 8.0.19以降変わったのは mysqlクライアントの binary_as_hex のデフォルト値だけであり、挙動そのものは、もともとそういうものだったのかもしれません。
(そして NULL に対しては表示処理で NULLを返すけど、未定義に対してはHEX化をトライしてしまうという、、やっぱり単に if 文の条件抜けのような気がしないでもない(昔から))
When the mysql client operates in interactive mode, the --binary-as-hex option now is enabled by default. In addition, output from the status (or \s) command includes this line when the option is enabled implicitly or explicitly:
Binary data as: Hexadecimal
To disable hexadecimal notation, use --skip-binary-as-hex (Bug #24432545)
たしかに、STATUS出力に新しい項目が1行加わっている!
mysql> status
- -
mysql Ver 8.0.20 for Linux on x86_64 (MySQL Community Server - GPL)
Connection id: 11
Current database:
Current user: root@localhost
SSL: Not in use
Current pager: stdout
Using outfile: ''
Using delimiter: ;
Server version: 8.0.20 MySQL Community Server - GPL
Protocol version: 10
Connection: Localhost via UNIX socket
Server characterset: utf8mb4
Db characterset: utf8mb4
Client characterset: utf8mb4
Conn. characterset: utf8mb4
UNIX socket: /var/run/mysqld/mysqld.sock
Binary data as: Hexadecimal
Uptime: 3 hours 49 min 39 secThreads: 3 Questions: 61 Slow queries: 0 Opens: 558 Flush tables: 4 Open tables: 36 Queries per second avg: 0.004