今回は第99回 mysqlコマンドラインクライアントでSQLをファイルから実行するで紹介させていただいた、ファイルに記載した内容をMySQL Shellで実行する方法について紹介していきたいと思います。
検証環境
今回はDockerで建てたMySQLを使用します。以下のコマンドでDockerを建ててローカルからアクセスをします。
% docker run --platform linux/x86_64 -p 127.0.0.1:3307:3306 -e MYSQL_ROOT_PASSWORD=my-secret-pw -e MYSQL_USER=kk2170 -e MYSQL_PASSWORD=my-secret-pw -d mysql:8.0.36 --secure-file-priv='/tmp'
今回はテストデータとして第2回 MySQLにはじめてのデータを入れてみるで紹介されている--secure-file-priv='/tmp'
を指定しています。
コンテナ内にunzipが入っていないため、unzipからiconvまでのコマンドをローカルで行い、docker cpでファイルを事前に送り、その後LOAD DATA INFILEを実行しています。
ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement
というエラーが表示された場合は、KEN_--secure-file-priv='/tmp'
配下にあるか確認してみてください。
今回も第215回や第214回と同様にDockerのイメージにあるMySQL Shellを使用して接続をしていきます。まずは、対話モードでも実行を行いたいので対話モードでJavaScriptを実行します。
立ち上げたDockerコンテナの中に入るためにコンテナIDを調べます。
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 5480636b729f mysql:8.0.36 "docker-entrypoint.s…" 12 seconds ago Up 10 seconds 33060/tcp, 127.0.0.1:3307->3306/tcp elastic_lederberg
続いて、Docker execコマンドを使用してMySQLのコンテナ内部に入ります。その後、mysqlshコマンドでログインを済ませます。
$ docker exec -it 5480636b729f bash # mysqlsh 〈中略〉 MySQL localhost JS >
中略された部分に関して詳細が知りたい場合は、第214回で説明を行っているので、そちらを参照してください。執筆時点では以下の通りMySQL 8.
MySQL localhost JS > \sql select version(); Fetching global names for auto-completion... Press ^C to stop. +-----------+ | version() | +-----------+ | 8.0.36 | +-----------+ 1 row in set (0.0001 sec)
バッチモードで実行してみる
さっそくですが、バッチモードで実行してみましょう。
$ cat shibuya.sql select zip_code from zipcode.zipcode where city like "%渋谷区%" order by zip_code;
第99回でも使用した、このSQLを実行してみましょう。このクエリは渋谷区に該当する郵便番号のデータを取得するSQLです。MySQL Shellでバッチ的に起動するには--file
オプションを付けて実行しましょう。
bash-4.4# mysqlsh --file shibuya.sql zip_code 1500000 〈中略〉 1510072 1510073
このように実行することができました。
SQLに関してはこんな感じで動く事がわかったのですが、では、JavaScriptとPythonはどうなるでしょうか? testという文字列を表示するprint.
bash-4.4# cat print.js print('test') bash-4.4# cat print.py print('test')
それぞれ同様にprint文を実行します。print.
bash-4.4# mysqlsh --file print.js testbash-4.4#
ちょっとわかりにくいのですが、testと表示されている事がわかります。続いてpythonを実行してみましょう。
bash-4.4# mysqlsh --file print.py test bash-4.4#
こちらは改行されて表示されています。このように勝手に--file
オプションの引数として渡すと、拡張子を見て判定して実行してくれます。ちなみに、shibuya.
bash-4.4# mysqlsh --file shibuya SyntaxError: Unexpected identifier 'zip_code' at shibuya:1:9 in select zip_code from zipcode.zipcode where city like "%渋谷区%" order by zip_code; ^^^^^^^^
--file
を付けて実行する際は、拡張子はしっかりと付けましょう。
コマンドから渡す
その他にもSQLを実行する方法があります。標準入力を使って指定する方法です。
cat shibuya.sql | mysqlsh --sql zip_code 1500000 〈中略〉 1510072 1510073
こちらはshibuya.--sql
はSQLモードとして起動するという事を行っています。SQLモードとして起動するため、起動後に標準入力で渡されたSQLが実行されて結果が得られます。
同様に--py
や--python
とすると、Pythonが実行できます。
bash-4.4# cat print.py | mysqlsh --py test bash-4.4#
このようにPythonが実行されていることがわかります。
JavaScriptがデフォルトのためあまり無いと思いますが、JavaScriptを実行したい場合は--js
や--javascript
をつけて実行しましょう。
bash-4.4# cat print.js | mysqlsh testbash-4.4#
このようにJavaScriptが実行されていることがわかります。
あまり無いとは思いますが、PythonとしてもJavaScriptとしても解釈可能なプログラムを実行させようとした場合に想定していない言語で動いてしまうことを防ぐことにもつながるため、標準入力から扱う方が明示的でわかりやすいといえます。
その他、mysqlコマンドラインクライアントのように-e
オプションを使って実行することもできます。
mysqlsh --sql -e 'select zip_code from zipcode.zipcode where city like "%渋谷区%" order by zip_code;' zip_code 1500000 〈中略〉 1510072 1510073
-eオプションもモード指定をしないと、デフォルトに指定したモードで実行されます。特に指定が無ければJavaScriptとして実行されます。
まとめ
今回はMySQL Shellでプログラムをバッチ的に実行する方法を紹介しました。第99回のまとめでも説明させていただきましたが、運用を行う際に何らかのスクリプトファイルとして定義ができた方がレビューや実行漏れなどが少なくなるため、副作用が伴うデータベースの操作を行う際には必須となると思います。
また、複雑なSQLやちょっと保存して別の値に加工をしてUPDATEしたい場合などに、JavaScriptやPythonといったスクリプト言語が使用できる事は、かなりの強みになると思います。
MySQLの標準的な機能だけで簡易的な加工や複雑な処理が行えることにつながるので、ぜひ一度試してみてはいかがでしょうか。