MySQL 8.0.19 で追加された TABLE と VALUES

1/13 に MySQL 8.0.19 がリリースされたんで、リリースノート を眺めてると気になるのがいくつか。

Important Change: MySQL now supports explicit table clauses and table value constructors according to the SQL standard. These have now been implemented, respectively, as the TABLE statement and the VALUES statement

TABLE と VALUES ステートメントが追加されたみたい。 さすがMySQL! パッチリリースで新しい構文を突っ込んでくるッ! そこにシビれる!あこがれるゥ!

TABLE

TABLE は、テーブルの中身全部を取り出す SELECT のようなものらしい。

TABLE tSELECT * FROM t と同じ意味らしい。WHERE や JOIN は使えない(ORDER BY と LIMIT はある)。

mysql> SELECT * FROM t;
+------+-------+
| id   | value |
+------+-------+
|    1 | abc   |
|    2 | xyz   |
+------+-------+
2 rows in set (0.01 sec)

mysql> TABLE t;
+------+-------+
| id   | value |
+------+-------+
|    1 | abc   |
|    2 | xyz   |
+------+-------+
2 rows in set (0.00 sec)

誰得なのかわからん…。サブクエリ中の SELECT を簡単に書けるようになるくらい?

VALUES

VALUES はレコードセットをリテラルで書けるらしい。 カラム名は column_N になる。

mysql> VALUES ROW(1,2,3), ROW(3,2,1);
+----------+----------+----------+
| column_0 | column_1 | column_2 |
+----------+----------+----------+
|        1 |        2 |        3 |
|        3 |        2 |        1 |
+----------+----------+----------+
2 rows in set (0.00 sec)

ROW が余計な気がする。PostgreSQL は ROW が要らなくて、INSERT の VALUES 句と同じように書けるっぽい。

VALUES にも ORDER BY と LIMIT はある。

mysql> VALUES ROW(1,2,3), ROW(3,2,1) ORDER BY column_2 LIMIT 1;
+----------+----------+----------+
| column_0 | column_1 | column_2 |
+----------+----------+----------+
|        3 |        2 |        1 |
+----------+----------+----------+
1 row in set (0.00 sec)

けど、ORDER BY を指定しない LIMIT は効かないみたい。バグなのかな…。

mysql> VALUES ROW(1,2,3), ROW(3,2,1) LIMIT 1;
+----------+----------+----------+
| column_0 | column_1 | column_2 |
+----------+----------+----------+
|        1 |        2 |        3 |
|        3 |        2 |        1 |
+----------+----------+----------+
2 rows in set (0.00 sec)

VALUES の方は嬉しいことがあるかもしれない。集計系のクエリで結果テーブルに表れない項目のレコードを足したりとか。

mysql> SELECT name, COUNT(*) cnt FROM t GROUP BY name;
+---------+-----+
| name    | cnt |
+---------+-----+
| 製品A   |   2 |
| 製品C   |   1 |
| 製品E   |   3 |
+---------+-----+
3 rows in set (0.00 sec)

mysql> SELECT name, IFNULL(cnt,0) AS cnt
 FROM (SELECT name, count(*) AS cnt FROM t GROUP BY name) AS a
 RIGHT JOIN (VALUES ROW('製品A'), ROW('製品B'), ROW('製品C'), ROW('製品D'), ROW('製品E')) AS b(name)
 USING (name);
+---------+-----+
| name    | cnt |
+---------+-----+
| 製品A   |   2 |
| 製品C   |   1 |
| 製品E   |   3 |
| 製品B   |   0 |
| 製品D   |   0 |
+---------+-----+
5 rows in set (0.00 sec)

しかし名前が TABLE と VALUES なのか…。動詞じゃないことに違和感。標準SQLらしいけど。