MySQLをMacのターミナルで操作するときのメモ

毎度てんやわんやするので整理メモを残します。
随時更新します。

ご指摘・代替案等ありましたらコメントいただけますと幸いです。

# 環境状況
- Mac OSCatalina 10.15.2
- MySQL 8.0.19（Homebrewで`brew install mysql`して入れたもの）
- ターミナルでの作業

#### 懸念点
・/usr/local/opt配下に"mysql"と"mysql＠8.0"がある
（バージョンはどちらも同じ）
→ 以前ポート番号が0になって接続できなかったことがあり、そのときの原因はこの見る先の問題かも？と想定（`mysqladmin shutdown`にて解決）

・何回もインストールし直している
どこかでなにやらやばいことになってないか不安:thinking:

（追記）
何をやっても動かなくなったので一からやり直しました
[どうしよう！困った時のMac上のMySQLのアンインストール＆再インストール、動作確認手順 | Qiita](https://qiita.com/akiko-pusu/items/aef52b723da2cb5dc596)
[MacでMySQL5.7をアンインストールする | Qiita](https://qiita.com/sato11/items/ba887a5655217f60f2a2)
[MySQL8.0をmacOSにインストールする方法 | プログラミング入門ナビ](https://programmingnavi.com/35/)

# 知識
個人的に覚えておきたいこと:writing_hand:

- MySQLの設定は**/etc/my.cnf**（[参考 - Qiita](https://qiita.com/at_1016/items/874788e375938837a027)）
- MySQL 8.0では、**ホストサーバーにログインしないでも設定値の変更から再起動で反映までコマンドでできる**ようになった（[参考 - スマートスタイル TECH BLOG](https://www.s-style.co.jp/blog/2018/09/2527/)）
- 基本的にSQLは大文字でも小文字でも大丈夫
    - 小文字だとダメだったときがあるけど、それはそもそも文を間違えてた可能性もある
- Macのターミナルで**コマンドが実行できない＆改行しかできない地獄**に陥ったときは`control + c`
    - `/C`でも`\c`でも`command + c`でもなく**control + c**
- MySQL 8.0から**ユーザ作成と権限付与は別々で**ちゃんと行わないといけなくなった
- rootは元々パスワードがついていないので付けた方がいい（[参考 - CodeCampus](https://blog.codecamp.jp/root-password)）
- MySQL内で設定を変えたら、基本的には一回出る

☆ MySQLの状態を調べる
（MySQL内から状態を見るパターンは後述）
・情報を見たいとき
`$ brew info mysql`
・バージョン確認
`$ mysql --version`
（[参考 - Qiita](https://qiita.com/fuwamaki/items/194c2a82bd6865f26045)）


# コマンド実行
☆ 文頭の違い
`$`：通常のターミナルでの操作
`mysql>`：MySQLにログインしてからの操作 → 文末に`;`がないと実行されない

## 基本操作

### MySQLの起動
```terminal
$ mysql.server start
```
`$ mysql.server start --skip-grant-tables`
→ パスワードなしでログインできる

### MySQLにログイン（実行、接続とも）
```terminal
$ mysql -u root -p
```
「**「ユーザ名：root」で接続**します、**パスワードは後で聞いて**」という意味
らしい（[抜粋元 - プロエンジニア](https://proengineer.internous.co.jp/content/columnfeature/6584)）
このコマンドの後、パスワードが聞かれるので入力する（打ったパスワードは画面に表示されない）

### MySQLからログアウト
```terminal
mysql> exit
```
`quit`でも`\q`でも可

### MySQLの停止（終了とも）
```terminal
$ mysql.server stop
```
バッテリーを消耗しやすいため、使わないときは停止させておいた方がいいらしい

### MySQLの再起動
```terminal
$ mysql.server restart
```

### MySQLの自動起動
```terminal
$ brew services start mysql
```
Homebrewの機能（多分）
重複起動させたりしてわけわからんことになるので、
調べながらやってるビギナーなうちは**やらない方がいい**と思った
何度も事故った:head_bandage:

☆ 止めたいときは
`$ brew services stop mysql`

（[参考 - Qiita](https://qiita.com/kichinaga/items/699e3f7b07bbee6f4a96)）

## MySQL関連
どうなってるか見る

```terminal
mysql> show variables like 'version'; #バージョン確認
mysql> show status; #セッション統計情報の表示
mysql> show status like "Threads_connected"; #現在の同時接続数を表示
```
（[参考 - Qiita](https://qiita.com/fuwamaki/items/194c2a82bd6865f26045)）

## ユーザ関連
前述のログインするユーザに関連

rootだとなんでもできてしまってこわいので、
必要に応じて別途DBを利用するユーザを作っておいた方がいい

### 現在のユーザ確認
```terminal
mysql> SELECT user(); # ログイン中のユーザ表示
mysql> SHOW GRANTS; # 現在ログイン中ユーザの権限確認
```

### ユーザ一覧の表示
```terminal
mysql> SELECT user, host FROM mysql.user;
```
mysqlというデータベースにあるuserテーブルにアクセス
他にもいろんなカラムがある

### ユーザの作成
```terminal
mysql> CREATE USER '[作成したいユーザ名]'@'[ホスト名]' IDENTIFIED BY '[指定したいパスワード]';
```
ホスト名には、MySQLへ接続するホストを指定する
ホスト名の代わりにIPアドレスやlocalhostを指定することも可（[参考 - プロエンジニア](https://proengineer.internous.co.jp/content/columnfeature/6638)）

### ユーザの削除
```terminal
mysql> DROP USER '[削除したいユーザ名]'@'[ホスト名]';
```

### ユーザの権限付与
```terminal
mysql> GRANT [権限] ON [適用対象のデータベース].[適用対象のテーブル] TO '[権限付与するユーザ名]'@'[ホスト名]';
mysql> FLUSH PRIVILEGES; # 権限の変更をデータベースに反映
```
＜Point 1＞
検索すると以下のような書き方がよく出てくる
> GRANT [権限] ON [適用対象のデータベース].[適用対象のテーブル] TO '[権限付与するユーザ名]'@'[ホスト名]' IDENTIFIED BY '[パスワード]';

が、MySQL 8.0の場合[ユーザ作成と権限付与は別で行わないといけない](https://qiita.com/egnr-in-6matroom/items/e77dfc719ed3dfbe0027)ので、文末に`IDENTIFIED BY '[パスワード]'`を書いて実行すると構文エラーになる[^1]:space_invader:

＜Point 2＞
権限の書き方、種類、権限付与により操作を許可するDBやテーブルの書き方は、以下参考URLの該当項目を参照
[MySQLでユーザを作成し、権限を設定する方法 | プロエンジニア](https://proengineer.internous.co.jp/content/columnfeature/6638)

### 対象ユーザの権限を確認
```terminal
mysql> SHOW GRANTS FOR '[ユーザ名]'@'[ホスト名]';
```

### 対象ユーザのパスワード変更
```terminal
mysql> UPDATE mysql.user SET password=password('[新パスワード]') WHERE user='[対象ユーザ]';
mysql> FLUSH PRIVILEGES; # 権限変更を反映
```

### 対象ユーザの権限を削除
```terminal
mysql> REVOKE [権限] ON [適用対象のデータベース].[適用対象のテーブル] FROM '[権限を削除するユーザ名]'@'[ホスト名]';
mysql> FLUSH PRIVILEGES; # 権限変更を反映
```

## データベース関連
ほぼ抜粋
[Macでmysqlを扱う方法 | Qiita](https://qiita.com/fuwamaki/items/194c2a82bd6865f26045)
※自分の実行結果に修正・追記予定

### データベース確認
```terminal
mysql> SHOW databases; #データベース一覧を表示
mysql> USE [データベース名] #使用するデータベースを選択（セミコロン不要）
mysql> CREATE database [データベース名]; #データベースの作成
mysql> DROP database [データベース名]; #データベースの削除
```

### テーブル確認
```terminal
mysql> SHOW tables; # テーブル一覧を表示
mysql> SHOW tables status; # テーブル一覧のステータス情報を表示
mysql> DESC [テーブル名]; # カラム一覧を表示
mysql> SHOW full columns FROM [テーブル名]; # カラム一覧を表示、Collation付き。
```
※Collation：照合順序。MySQLでは文字コードとソート順を持っており、ソート順の部分がCollationと呼ばれている。DB単位、テーブル単位、カラム単位で設定可能である。

### インデックス確認
```terminal
mysql> SHOW index FROM [テーブル名]; # 特定のテーブル

mysql> USE information_schema;
mysql> SELECT * FROM statistics WHERE TABLE_SCHEMA = [データベース名]; # 特定のデータベース
```
（[参考 - Qiita](https://qiita.com/merrill/items/967884c02e10bd8f32f5)）

## mysqladminコマンド
管理操作を実行するためのクライアント
MySQL サーバの稼動状況を確認したり、MySQL サーバを停止したりできる
（[参考 - MySQL 逆引きリファレンス](http://mysql.javarou.com/cat/177/)）

**MySQLにログインしていない状態で使う**
→ `$ mysqladmin ～`

このひとがいつ使うなんなのかわからなくてしっちゃかめっちゃかになったりした
`mysql> ～`の処理とごちゃまぜに書いてあるサイトが多くて混乱したので、
実際に使うときはしっかり区別する

#### ☆ パスワード送信オプション
`-u [ユーザー名] -p` ← これのこと
後述のmysqladminコマンドを実行する際、
**パスワードを設定しているユーザが対象である場合**は文末に記述する
そうしないと権限エラーになる
>（例）$ mysqladmin ping **-u root -p**

パスワードを設定していないユーザであれば書かなくてもいける
（以下パスワード送信オプションの記述は省略します）

### MySQL サーバが起動中であるかを確認
```terminal
$ mysqladmin ping 
```
MySQLサーバを起動していない場合は、
パスワードを設定していても`$ mysqladmin ping`でわかる（エラー内容から）

### MySQL サーバの状態を表示
```terminal
$ mysqladmin status
$ mysqladmin extended-status #詳細情報
```

### ユーザーのパスワードを変更
```terminal
$ mysqladmin password [新パスワード] -u [ユーザー名] -p
```
＜Point 1＞
**`[新パスワード]`の部分はそのままパスワードを書く**
いつもみたいに`'pass12345'`とか書くと、パスワードが**pass12345**ではなく**'pass12345'**になる
（シングルクォーテーションもパスワードになっちゃう）

＜Point 2＞
コマンドの履歴を記載するログファイルに
パスワードが残ってしまうらしいので、セキュリティ的にはよろしくない
（[参考 - CodeCampus](https://blog.codecamp.jp/root-password)）

### mysqladmin コマンドのヘルプを表示
```terminal
$ mysqladmin -?
```
※パスワード送信オプション不要

### 実行中のプロセスの一覧を表示
```terminal
$ mysqladmin processlist
```

### プロセス（処理中の接続）を強制的に停止
```terminal
$ mysqladmin kill [プロセスID]
```
＜Point 1＞
プロセスID の一覧は`mysqladmin processlist`で調べられる

＜Point 2＞
強制的に終了するプロセスを`,`（カンマ）区切りで複数指定できる
その際、**カンマの後ろに半角スペースを含めてはいけない**:no_good:
`1111, 2222, 3333, ...`のように書くとコマンドが正しく実行されなくなる
>（正解例）1111,2222,3333, ...

# 気を付けたいポイント
・「同じ処理内容に見えるけど、書き方が全然違う」ときはなんらかの違う理由があるので、適当にやらずにちゃんと違いを理解する
→ 適当にやると余計なもの同士ががっちゃんこしたりする

・ターミナル系でコケるとき、基本的に「何をするコマンドなのか」をわかっていないのが原因なので、わからないことを分解して調べる

・エラーメッセージは丸々ググる前に英文を理解してから

・書いてある通りにやってできなかったらバージョンの違いを確認する


[^1]: つまり、この書き方はユーザ作成と権限付与をまとめてやってるやつ