目次
とある日
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
テーブル演算子のサポート
今回のアップデートで一番の目玉機能ですね。
このリリースでは、MySQL は SQL 標準
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は結果が異なるということです。
- TABLE test1 EXCEPT TABLE test2 INTERSECT TABLE test3;
- TABLE test1 EXCEPT (TABLE test2 INTERSECT TABLE test3);
- (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 日、一般公開)