MySQL道普請便り

第193回VALUESステートメントとTABLEステートメントを使ってみよう

MySQLはバージョン8.0.19以降、VALUESステートメントとTABLEステートメントが導入されました。VALUESステートメントはデータを操作するDMLの1つで、1つ以上の行のセットをテーブルとして返すステートメントになります。TABLEステートメントは指定されたテーブルの行とカラムを返します。今回はこのVALUESステートメント、TABLEステートメントについて紹介したいと思います。なお、今回利用するMySQLのバージョンは8.0.31となります。

VALUESステートメント

冒頭でも紹介しましたように、VALUESステートメントは1つ以上の行のセットをテーブルとして返すステートメントです。VALUESステートメントは、VALUESのあとにROW()で指定された1つ以上の行コンストラクタのリストで構成されます。早速実際に利用してみましょう、

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

(column_0, column_1)に対して(1 ,2)が返されました。

複数行を返す場合は、ROW(),ROW()…というように、行コンストラクタをカンマ区切りで指定することで表現することができます。また、列名はcolumn_0, column_1, column_2…のように、常に0から始まるcolumn_Nで暗黙的に名付けられます。

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

この行コンストラクタには同じカラム内で型を混在することが可能で、関数も利用することができます。実際に型の違う組み合わせやNULL値、NOW()関数を利用して出力してみましょう。

mysql> VALUES ROW(1,2),ROW('abc', 0.345),ROW(NULL,NULL),ROW(current_user(),now());
+----------------+---------------------+
| column_0       | column_1            |
+----------------+---------------------+
| 1              | 2                   |
| abc            | 0.345               |
| NULL           | NULL                |
| root@localhost | 2023-03-22 06:26:23 |
+----------------+---------------------+
4 rows in set (0.00 sec)

また、LIMIT句を使ってVALUESステートメントで出力する行数の制限をすることも可能です。

mysql> VALUES ROW(1,2),ROW('abc', 0.345),ROW(NULL,NULL),ROW(current_user(),now()) LIMIT 1;
+----------+----------+
| column_0 | column_1 |
+----------+----------+
| 1        | 2        |
+----------+----------+
1 row in set (0.00 sec)

利用する際にROW()の中身のが空であったり、他の行コンストラクタと数が合わない場合は、エラーとなり利用できません。

mysql> VALUES ROW();
ERROR 3942 (HY000): Each row of a VALUES clause must have at least one column, unless when used as source in an INSERT statement.
mysql> VALUES ROW(1,2),ROW(3);
ERROR 1136 (21S01): Column count doesn't match value count at row 2

他のステートメントと組み合わせて利用してみる

VALUESステートメントはUNIONやJOINと組み合わせて利用することが可能です。これを利用することで、足りない行を補ったり、コードで管理しているマッピングデータをVALUESで表現してデータを参照するといったことが可能になります。

リスト UNIONを利用する
mysql> (SELECT * FROM test LIMIT 3 ) UNION VALUES ROW(5,'e');
+----+-------+
| id | name1 |
+----+-------+
|  1 | a     |
|  2 | b     |
|  3 | c     |
|  5 | e     |
+----+-------+
4 rows in set (0.00 sec)
リスト JOINを利用する
mysql> SELECT column_1, count(1) FROM t1 LEFT OUTER JOIN (VALUES ROW(1,'ON'), ROW(0, 'OFF')) as t ON flag = column_0 GROUP BY column_1;
+----------+----------+
| column_1 | count(1) |
+----------+----------+
| ON       |        3 |
| OFF      |        2 |
+----------+----------+
2 rows in set (0.00 sec)

その他

VALUESステートメントのドキュメントにはORDER BY句の利用についてもかかれていますが、バージョン8.0.31では期待通りの動作を確認することができませんでした。これはおそらくバグかと思われますので、ORDER BY句を利用したい場合は修正されるのを待ちましょう。

TABLE ステートメント

TABLEステートメントはTABLE <table_name>とすることで指定されたテーブルの行とカラムを返します。また、TABLEステートメントはORDER BY、LIMIT、OFFSETがサポートされており、行の並び替えや出力する行数の制限をすることができます。

mysql> TABLE t1;
+------+
| flag |
+------+
|    1 |
|    0 |
|    1 |
|    1 |
|    0 |
+------+
5 rows in set (0.00 sec)

SELECTステートメントと似た動作ですが、以下の点で違いがあります。

  • SELECTステートメントはカラム名を指定することで表示するカラムを制限することができるが、TABLEステートメントは、常にテーブルのすべてのカラムが表示される
  • SELECTステートメントはWHERE句を使って条件を指定することができるが、TABLE ステートメントはWHERE 句を利用して行を制限することができない

上記のような違いはありますが、UNIONやサブクエリとして利用することは可能です。

リスト サブクエリの利用
mysql> SELECT * FROM t2 WHERE num IN (TABLE t1);
+------+
| num  |
+------+
|    2 |
|    4 |
|    2 |
|    4 |
+------+
4 rows in set (0.01 sec)
リスト UNIONを利用
mysql> TABLE t2 union TABLE t1;
+------+
| num  |
+------+
|    2 |
|    4 |
|    6 |
|    8 |
|    1 |
|    0 |
|    3 |
+------+
7 rows in set (0.00 sec)

まとめ

今回は簡単ではありますが、VALUESステートメントとTABLEステートメントについて紹介しました。サクッと行の中身を見たい場合や行を補いたい場合に便利なので、もし利用できるタイミングがあれば利用してみてください。

VALUESステートメントTABLEステートメントについての公式ドキュメントも準備されているので、こちらもぜひご一読ください。

おすすめ記事

記事・ニュース一覧