2018年1月30日火曜日

MySQL 8.0.4でMySQLの正規表現演算がだいぶマシになる


TL;DR

  • MySQL 5.7とそれ以前にも一応 REGEXP演算子 (またはRLIKE演算子)はあって、多少正規表現っぽいことはできるんだけど正規表現としては全然物足りなかった。
    • 少なくとも \s で空白文字にマッチできないとかちょっとPerlの正規表現で甘やかされた身にとってはつらい
    • しかも遅いんだこれが
    • あとマルチバイト非対応(マルチバイトに対して使おうと思ったことないけど)
  • MySQL 8.0.4とそれ以降ではICUの正規表現エンジンを使うことでかなーりマシに。

古くからこういう使い方はできた。
カラム名 REGEXP '正規表現文字列' (俺はRLIKEの方が好きでRLIKEって書くけどREGEXP演算子と意味は一緒、カラム名で使うことが多いけど正しくは判定文字列)
mysql57 5> SELECT * FROM t1 WHERE text RLIKE '^MySQL 5.[67]' LIMIT 3;
+--------------------+---------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| tweet_id           | timestamp           | text                                                                                                                                                                |
+--------------------+---------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 252971369963335681 | 2012-10-02 12:20:49 | MySQL 5.6.7のチェンジログにしっかり見つけた。。 http://t.co/fR5yc3vD                                                                                                |
| 342484389072093184 | 2013-06-06 12:33:36 | MySQL 5.6.12 has still this bugってPHPから叩くときのこと?

MySQL Bugs: #69027: Default secure_auth value breaking PHP connects http://t.co/yx2f54Viwp             |
| 343936149896720384 | 2013-06-10 12:42:22 | MySQL 5.6 root ログインできない っていう検索トラフィック増えてきてるんですけど。 。orz                                                                               |
+--------------------+---------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+
3 rows in set (0.01 sec)

mysql57 5> SELECT * FROM t1 WHERE text RLIKE 'MySQL\\sEnterprise' LIMIT 3;
Empty set (0.51 sec)

mysql57 5> SELECT * FROM t1 WHERE text RLIKE '^マイ[エ]ス' LIMIT 3;
Empty set (0.06 sec)
新しい正規表現は REGEXP_LIKE関数 で提供されるけれど、今までどおりのRLIKE, REGEXP演算子を使った書き方もできる。その場合でも使う正規表現エンジンはICU版。
mysql80 13>SELECT * FROM t1 WHERE text RLIKE '^MySQL 5.[67]' LIMIT 3;
+--------------------+---------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| tweet_id           | timestamp           | text                                                                                                                                                                |
+--------------------+---------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 252971369963335681 | 2012-10-02 12:20:49 | MySQL 5.6.7のチェンジログにしっかり見つけた。。 http://t.co/fR5yc3vD                                                                                                |
| 342484389072093184 | 2013-06-06 12:33:36 | MySQL 5.6.12 has still this bugってPHPから叩くときのこと?

MySQL Bugs: #69027: Default secure_auth value breaking PHP connects http://t.co/yx2f54Viwp             |
| 343936149896720384 | 2013-06-10 12:42:22 | MySQL 5.6 root ログインできない っていう検索トラフィック増えてきてるんですけど。 。orz                                                                               |
+--------------------+---------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+
3 rows in set (0.01 sec)

mysql80 14> SELECT * FROM t1 WHERE text RLIKE 'MySQL\\sEnterprise' LIMIT 3;
+--------------------+---------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| tweet_id           | timestamp           | text                                                                                                                                                                                                                                                  |
+--------------------+---------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 366900653253070848 | 2013-08-12 21:35:07 | RT @mysql_japan: MySQL Workbench 6.0がGAになりました。UIのデザインが変更となった ほか、新たにMySQL Enterprise Editionの機能のUIも加わっています。 http://t.co/aiQM21dPZ5 #MySQL #my…                                                                   |
| 385784283853365249 | 2013-10-04 00:11:55 | MySQL Enterprise Monitorのバグレポート一気に増えてるねぇ。                                                                                                                                                                                            |
| 404150382252670976 | 2013-11-23 16:32:14 | RT @h141gm: バックアップの方法
  mysqldump
  コールドバックアップ
  スナップショット(→要リカバリ)
  バイナリログ
  MySQL Enterprise Backup (差分取得も可)
  レプリケーション利用
#ost2013                                                           |
+--------------------+---------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
3 rows in set (0.04 sec)

mysql80 13> SELECT * FROM t1 WHERE text RLIKE '^マイ[エ]ス' LIMIT 3;
+--------------------+---------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+
| tweet_id           | timestamp           | text                                                                                                                                                      |
+--------------------+---------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+
| 372177762645053440 | 2013-08-27 11:04:28 | マイエスキューエる。                                                                                                                                      |
| 563640699841560576 | 2015-02-06 19:09:49 | マイエス☆キューエル                                                                                                                                       |
| 747379558760931328 | 2016-06-27 19:42:27 | マイエスキューエルファブリック。是非、声に出していただきたい。なんか響きがかっこ いい気がしてくるから。                                                    |
+--------------------+---------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+
3 rows in set (0.05 sec)
いいねいいね。
RLIKE演算子ではなくて REGEXP_LIKE(カラム名, '正規表現文字列', 'マッチタイプ') を使うとIgnore Caseができるようになる。マッチタイプは省略可能。
mysql80 15> SELECT * FROM t1 WHERE REGEXP_LIKE(text, 'mysql', 'i') LIMIT 3;
+--------------------+---------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| tweet_id           | timestamp           | text                                                                                                                                                                                                                             |
+--------------------+---------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 167925415959199744 | 2012-02-10 19:58:33 | myspiをmysqlに空目… RT @lifehackerjapan: 最新記事: あごを脱力して心の中で「アー」と言う!? 薬なしでも不眠を克服できる簡単なテクニック #myspi http://t.co/6pueAVSf #lh_jp                                                         |
| 188134150971203586 | 2012-04-06 14:20:51 | MySQL DBA試験に向けて追い込み。                                                                                                                                                                                                  |
| 188280387879968768 | 2012-04-07 00:01:57 | MySQL DBA受検の為にLinuxにもMySQL入れとこう⇒VirtualBox使ってCentOS入れる(2日)⇒FEDERATEDとNDB使いたいからソースからコンパイルしよう(1日)⇒試験まであと3日(昨日の夜ここ)                                                            |
+--------------------+---------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
3 rows in set (0.00 sec)
OLTPの中で使うことはないだろうけど、ちょっとした飛び道具にRLIKEはそこそこ好きなのでちょっとだけ嬉しい。


【2018/01/30 16:54】
なお、ドキュメントにはしゃらっと書かれているけれど

Because MySQL uses the C escape syntax in strings (for example, \n to represent the newline character), you must double any \ that you use in your expr and pat arguments.

なので、 '\s' をREGEXP_LIKEに渡す時は '\\s' にしてやらないといけない

0 件のコメント :

コメントを投稿