今日はなにの日。

気になったこと勉強になったことのメモ。

今日は、MySQL 8.0.31がリリースされたので触ってみたの日。

目次

とある日

2022 年 10 月 11 日にMySQL 8.0.31がリリースされました。

MySQL :: MySQL 8.0 Release Notes :: Changes in MySQL 8.0.31 (2022-10-11, General Availability)

時間がなくて気づいたら一ヶ月立ってました。

アップデートで気になったやつを触ってみました。

アップデート内容

引用符なしの識別子として「full」が非推奨

重要な変更: 以前、MySQLは、テーブル、列、ビュー、ストアド プロシージャ、またはストアド関数の名前、およびテーブル、ビュー、または列のエイリアスとして「full」の使用をサポートしていました。このリリース以降、引用符なしの識別子として「full」 (大文字と小文字を区別しない) をこのように使用することは推奨されなくなり、警告が発生します。FULLこれは、キーワードとして予約されている SQL 標準とより密接に連携するため

MySQL予約語に登録されるわけではないですが、推奨されない単語になりました。

やってみましたが、警告は出なかったです。

文字コードの関係なのかなぜか出なかったです。(関係なさそう)

(root@localhost) [test] 8.0.31 > CREATE TABLE full (c1 INT, c2 INT);
Query OK, 0 rows affected (0.05 sec)

(root@localhost) [test] 8.0.31 >  SHOW WARNINGS\G
Empty set (0.00 sec)

(root@localhost) [test] 8.0.31 > select version();
+-----------+
| version() |
+-----------+
| 8.0.31    |
+-----------+
1 row in set (0.02 sec)

環境はdocker-composeで立ててます。

  db6:
    image: mysql:8.0.31-debian
    container_name: mysql_ver_8.0.31
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: test
      MYSQL_USER: docker
      MYSQL_PASSWORD: docker
      TZ: "Asia/Tokyo"
    command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
    volumes:
      - ../../MySQL/settings/my.cnf:/etc/mysql/conf.d/my.cnf
      - ../../MySQL/settings/mylogin.sh:/root/mylogin.sh

cnfなしで起動しても同じでした。

本来はWARNINGSで警告が出ます。

SQL 標準 INTERSECTおよび EXCEPTテーブル演算子のサポート

今回のアップデートで一番の目玉機能ですね。

このリリースでは、MySQLSQL 標準 INTERSECTおよび EXCEPTテーブル演算子のサポートを追加します。

*query_a* INTERSECT *query_b*両方の結果セットに表示される行のみが含まれます。

*query_a* EXCEPT *query_b*の結果セットから、 の結果 query_aない行を返しますquery_b

概要

  • INTERSECT は2つのテーブルで共通する行が表示される
  • EXCEPT は2つのテーブルではじめのテーブルにない行が表示される

INTERSECT

MySQL :: MySQL 8.0 Reference Manual :: 13.2.10.4 INTERSECT Clause

(root@localhost) [test] 8.0.31 > TABLE test1;
+------+------+
| m    | n    |
+------+------+
|    1 |    2 |
|    2 |    3 |
|    3 |    4 |
+------+------+
3 rows in set (0.00 sec)

(root@localhost) [test] 8.0.31 > TABLE test2;
+------+------+
| m    | n    |
+------+------+
|    1 |    2 |
|    2 |    3 |
|    3 |    4 |
|    2 |   33 |
|    3 |   44 |
|    2 |   33 |
|    3 |   44 |
+------+------+
7 rows in set (0.00 sec)

(root@localhost) [test] 8.0.31 > TABLE test1 intersect  TABLE test2;
+------+------+
| m    | n    |
+------+------+
|    1 |    2 |
|    2 |    3 |
|    3 |    4 |
+------+------+
3 rows in set (0.00 sec)

EXCEPT

MySQL :: MySQL 8.0 リファレンスマニュアル :: 13.2.10.5 EXCEPT 句

(root@localhost) [test] 8.0.31 > TABLE test1;
+------+------+
| m    | n    |
+------+------+
|    1 |    2 |
|    2 |    3 |
|    3 |    4 |
+------+------+
3 rows in set (0.00 sec)

(root@localhost) [test] 8.0.31 > TABLE test2;
+------+------+
| m    | n    |
+------+------+
|    1 |    2 |
|    2 |    3 |
|    3 |    4 |
|    2 |   33 |
|    3 |   44 |
|    2 |   33 |
|    3 |   44 |
+------+------+
7 rows in set (0.00 sec)

(root@localhost) [test] 8.0.31 > TABLE test2 except TABLE test1;
+------+------+
| m    | n    |
+------+------+
|    2 |   33 |
|    3 |   44 |
+------+------+
2 rows in set (0.00 sec)

優先度

INTERSECTやEXCEPT、UNIONには優先度が存在します。

INTERSECTはEXCEPTまたはUNIONの前にグループ化されるので、TABLE r EXCEPT TABLE s INTERSECT TABLE tはTABLE r EXCEPT (TABLE s INTERSECT TABLE t)と評価される。

つまり、1と2は結果が同じですが3は結果が異なるということです。

  1. TABLE test1 EXCEPT TABLE test2 INTERSECT TABLE test3;
  2. TABLE test1 EXCEPT (TABLE test2 INTERSECT TABLE test3);
  3. (TABLE test1 EXCEPT TABLE test2) INTERSECT TABLE test3;
(root@localhost) [test] 8.0.31 > TABLE test3;
+------+------+
| m    | n    |
+------+------+
|   11 |    2 |
|    3 |   33 |
|    1 |    2 |
+------+------+
3 rows in set (0.00 sec)

(root@localhost) [test] 8.0.31 > TABLE test1 EXCEPT TABLE test2 INTERSECT TABLE test3;
+------+------+
| m    | n    |
+------+------+
|    2 |    3 |
|    3 |    4 |
+------+------+
2 rows in set (0.00 sec)

(root@localhost) [test] 8.0.31 > TABLE test1 EXCEPT (TABLE test2 INTERSECT TABLE test3);
+------+------+
| m    | n    |
+------+------+
|    2 |    3 |
|    3 |    4 |
+------+------+
2 rows in set (0.00 sec)

(root@localhost) [test] 8.0.31 > (TABLE test1 EXCEPT TABLE test2) INTERSECT TABLE test3;
Empty set (0.00 sec)

ALLとDISTINCT

INTERSECTとEXCEPTはどちらもDISTINCTとALLをサポートし、DISTINCTはどちらの場合もデフォルトです(UNIONと同じです)。(これはUNIONと同じです)。

重複行をまとめるかまとめないかの違いです。

(root@localhost) [test] 8.0.31 > TABLE test2 except all TABLE test1;
+------+------+
| m    | n    |
+------+------+
|    2 |   33 |
|    2 |   33 |
|    3 |   44 |
|    3 |   44 |
+------+------+
4 rows in set (0.00 sec)

(root@localhost) [test] 8.0.31 > TABLE test2 except TABLE test1;
+------+------+
| m    | n    |
+------+------+
|    2 |   33 |
|    3 |   44 |
+------+------+
2 rows in set (0.00 sec)

個人的に一番「へぇー」ってなったのはTABLEでSELECT * FROM tableの代わりになるという発見をしたことです。

参考記事

MySQL 8.0 の交差と除外 – lefred ブログ: MySQL エバンジェリストの苦難

MySQL :: MySQL 8.0 リファレンスマニュアル :: 13.2.10.5 EXCEPT 句

MySQL :: MySQL 8.0 リファレンスマニュアル :: 13.2.10.3 UNION 句

MySQL :: MySQL 8.0 リファレンスマニュアル :: 13.2.10.1 SELECT ... INTO ステートメント

MySQL :: MySQL 8.0 リファレンスマニュアル :: 13.2.10.4 INTERSECT 句

MySQL :: MySQL 8.0 リリース ノート :: MySQL 8.0.31 の変更点 (2022 年 10 月 11 日、一般公開)