[DB接続クライアント]mycliを導入してターミナルで気楽にMariaDB/MySQLを触る

![mycli_mysql_mariadb.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403039/b4f3c78a-ae68-b130-352d-de9b5e0d044e.png)

[Zenn](https://zenn.dev/kumamoto/articles/d2fa2826e0fc55)の方にも転載済です。(修正/加筆するときは両方で行います。)

# 前提 対象読者

- MariaDB(or MySQL)を導入済みであること。
まだ導入してないよーという初学者の方は、筆者が書いた[こちらの記事のMariaDB導入部分](https://qiita.com/digitalhimiko/items/438fb17706873b476040#mariadbmysql%E3%82%92%E5%B0%8E%E5%85%A5%E3%81%99%E3%82%8B)を参考にしてみてください。

- なんとなくSQLはわかる人
`SELECT`や`INSERT`など聞いたことはある、というレベルで問題ないと思います。
※ちゃんとSQLやRDB勉強したい方は『[スッキリわかる SQL 入門](https://www.amazon.co.jp/%E3%82%B9%E3%83%83%E3%82%AD%E3%83%AA%E3%82%8F%E3%81%8B%E3%82%8BSQL%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E3%83%89%E3%83%AA%E3%83%AB222%E5%95%8F%E4%BB%98%E3%81%8D-%E3%82%B9%E3%83%83%E3%82%AD%E3%83%AA%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-%E4%B8%AD%E5%B1%B1%E6%B8%85%E5%96%AC/dp/4295005096/ref=sr_1_2?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=%E3%82%B9%E3%83%83%E3%82%AD%E3%83%AA%E3%82%8F%E3%81%8B%E3%82%8B&qid=1607881626&sr=8-2) 』などの書籍からスタートしてみるのがオススメです！

- CLI(あのターミナルの黒い画面)でDBを気楽に弄ってみたい方
本格的に大規模なDBを弄るとなると[Sequel Pro](https://www.sequelpro.com/)などのGUIを使ったほうが流石に楽かと。
ただ個人開発とかちょっとした実験に触るにはmycliは気楽で良い...と思います。ターミナル触る訓練にもなるしね！

※本記事を英語で読みたい奇特な方は[dev.to](https://dev.to/digitalhimiko/use-mycli-and-learn-mariadb-mysql-comfortably-in-a-terminal-57cg)の方に筆者本人が上げている記事をどうぞ。

# 下準備 mycliをセットアップしよう

## そもそもmycliって何？

[mycli](https://www.mycli.net/)とは『MySQL(やMariaDB)などの一般的なDB管理システムのCLIインターフェイス』です。
※mycliはMySQL clientの略。CLIはCommand Line Interfaceのことです。

## で、mycliを使うと何が嬉しいの？

補完が入るのでターミナル上で楽にコマンドを打てる、typoが減るというのが一番良いところです。

- 基本コマンドに補完が入る
- テーブル名など補完候補が表示される
- カラーの設定が出来て見やすい

![mysql.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403039/7e1a5403-dd0f-9929-e589-0c2df7df15a0.png)
上記は普通のmysqlコマンドで接続した画面。見づらいしコマンドの補完も効かない...
![mycli_dis.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403039/18a8bba3-0f79-d633-df23-624ef122f0ab.png)
こちらはmycliコマンドで接続した画面。カラーがついて、候補も出るしステキ...!

## mycliのインストール

`pip`か`homebrew`を使ってインストールしていきましょう。

```
-- Mac使ってるなら下記で
$ brew update
$ brew install mycli
-- python使いなら下記でも
$ pip install mycli
```

mycliが入ったか確認してみてください。

```
$ mycli --version
Version: 1.21.1
```

## mycliのカラーなどを設定を変更する

設定ファイル`~/.myclirc`を[mycliの公式サイト](https://www.mycli.net/syntax)を参考に変更していきます。

```
# 色変更(若草色のようになります。)
syntax_style = native
# キーのバインディングをviに(vimキーバインドわからないならemacsのままでおｋ！)
key_bindings = vi
# 候補選択を広めに表示
wider_completion_menu = True
```

# mycliでMariaDB(MySQL)をイジってみる

## DBに接続する

DBまだ作ってない、どんなDBあったけという人は、データベース名を
省略して次の「データベース一覧を確認」をやってみましょう。

```
$ mycli -uユーザー名 -pパスワード データベース名
-- 例
$ mycli -uroot -pHOGEHOGE fuga_db
```

## データベース一覧を確認

```
> SHOW DATABASES;
```

## データベース作成

```
> CREATE DATABASE IF NOT EXISTS test;
```

## データベース削除
```
> DROP DATABASE IF EXISTS test;
```

## 接続先のホスト名の確認

```python
> SHOW VARIABLES LIKE 'hostname';
```

## テーブル作成

[CREATE TABLE 構文 / MySQL公式](https://dev.mysql.com/doc/refman/5.6/ja/create-table.html)

ちなみに下記のクエリでこんなテーブルを作ります。
![members.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403039/9abb62b4-d74c-c658-7e76-ca792ae9c6fb.png)
![posts.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403039/f4b0fe7c-5a54-a092-75cc-4f04def40761.png)
リレーションはこんな感じ([tbls](https://github.com/k1LoW/tbls)というツール叩いて作った即席ですが)
![スクリーンショット 2020-12-12 2.00.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403039/3932ef2f-b8bd-cf32-91a7-052ff083f2e6.png)

```
CREATE TABLE テーブル名 (カラム名 データ型 制約,...
FOREIGN KEY インデックス名 (カラム名, ...) 
   REFERENCES 参照先テーブル名 (カラム名, ...),
INDEX インデックス名(カラム名) COMMENT 'こめんと');

-- 例
> CREATE TABLE IF NOT EXISTS members (
id MEDIUMINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name varchar(255) NOT NULL UNIQUE,
email varchar(255) NOT NULL UNIQUE,
password varchar(100) NOT NULL,
picture varchar(255) NOT NULL DEFAULT '/default_icon.jpg',
created DATETIME NOT NULL,
modified TIMESTAMP NOT NULL,
-- インデックス/キーを貼るクエリは長くなりがちなので筆者は下記のように分けてます
INDEX idx_members_id_01(id) COMMENT 'for search member quickly'
);

> CREATE TABLE IF NOT EXISTS posts (
post_id MEDIUMINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
user_id MEDIUMINT NOT NULL,
content VARCHAR(900),
posted_at TIMESTAMP NOT NULL,
FOREIGN KEY fk_posts_userid_01(user_id)
	REFERENCES members (id)
);
```

## テーブルの一覧を表示

```
> SHOW TABLES;
```

## テーブルの構造を確認

[EXPLAIN 構文](https://dev.mysql.com/doc/refman/5.6/ja/explain.html)

```
-- DESCRIBEはEXPLAINのシノニム(同義語)です
> DESCRIBE テーブル名;
-- 例
> DESCRIBE members;
```

※参考
『[整数型(真数値) - INTEGER、INT、SMALLINT、TINYINT、MEDIUMINT、BIGINT / MySQL公式](https://dev.mysql.com/doc/refman/5.6/ja/integer-types.html)』

## テーブルのCREATE文を表示

[SHOW CREATE TABLE 構文](https://dev.mysql.com/doc/refman/5.6/ja/show-create-table.html)
DESCRIBE文より詳しい情報が得られます。

```
> SHOW CREATE TABLE テーブル名;
```

## テーブルを破棄

```
> DROP TABLE IF EXISTS テーブル名
You're about to run a destructive command.
Do you want to proceed? (y/n): y
Your call!
```

## indexを確認

```
> SHOW INDEX FROM テーブル名;
-- 例
> SHOW INDEX FROM members;
+---------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------------------+
| Table   | Non_unique | Key_name          | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment             |
+---------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------------------+
| members | 0          | PRIMARY           | 1            | id          | A         | 0           | <null>   | <null> |      | BTREE      |         |                           |
| members | 0          | name              | 1            | name        | A         | 0           | <null>   | <null> |      | BTREE      |         |                           |
| members | 0          | email             | 1            | email       | A         | 0           | <null>   | <null> |      | BTREE      |         |                           |
| members | 1          | idx_members_id_01 | 1            | id          | A         | 0           | <null>   | <null> |      | BTREE      |         | for search member quickly |
+---------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------------------+
```

上記の表示の意味は下記の通り。

|項目  |説明  |
|---|---|
|Table  |テーブルの名前  |
|Non_unique  |インデックスが重複を含むことができない場合は 0、できる場合は 1。  |
|Key_name  |インデックスの名前。このインデックスが主キーである場合、その名前は常に PRIMARY  |
|Seq_in_index  |インデックス内のカラムシーケンス番号であり、1 から始まる。  |
|Column_name  |カラム名  |
|Collation  |カラムのソート方法。MySQL では、これは「A」(昇順) またはNULL(ソートされない) のどちらかの値  |
|Cardinality  |「あるカラムにおける、取りうる値の種類」のこと。カーディナリティー(濃度)が高いほど、MySQL が結合を実行するときにこのインデックスを使用する可能性は高くなる。  |
|Sub_part  |カラムが部分的にしかインデックス設定されていない場合は、インデックス設定された文字の数。カラム全体がインデックス設定されている場合は NULL  |
|Packed  |キーがパックされる方法を示します。パックされない場合は NULL。  |
|NULL  |このカラムに NULL 値を含めることができる場合は YES が、できない場合は ''  |
|Index_type  |使用されるインデックス方法 (BTREE、FULLTEXT、HASH、RTREE)  |
|Comment  |このインデックスに関する情報(インデックスが無効になっている場合の disabled など)  |
|Index_comment  |インデックスが作成されたときに COMMENT 属性でインデックスに対して提供された任意のコメント  |

※参考
『[SHOW INDEX 構文 / MySQL公式](https://dev.mysql.com/doc/refman/5.6/ja/show-index.html)』
『[MySQL(InnoDB)でカーディナリティの低いカラムにINDEXを張る / Qiita記事](https://qiita.com/hmatsu47/items/2d44c173a9114fd06853)』

ちなみにインデックス方法のB-treeについては『[B-treeインデックス入門 / Qiita記事](https://qiita.com/kiyodori/items/f66a545a47dc59dd8839)』や『[これでわかるB-treeアルゴリズム / B-tree algorithm](https://speakerdeck.com/nekonenene/b-tree-algorithm)』などがオススメです。

とりあえず今はインデックスを上手に貼ると索引的なやつが出来て検索が早くなるのかな〜というイメージ(詳しい人に殴られそうな説明汗)で進んでもおｋです。

## 作成済のテーブルのカラムにindex追加

```
> ALTER TABLE テーブル名 ADD INDEX インデックス名(カラム名);
```

## indexを削除

[DROP INDEX 構文 / 公式](https://dev.mysql.com/doc/refman/5.6/ja/drop-index.html)
[ALTER TABLE 構文 / 公式](https://dev.mysql.com/doc/refman/5.6/ja/alter-table.html)

```
> DROP INDEX インデックス名 ON テーブル名
-- もしくは
> ALTER TABLE テーブル名 DROP INDEX インデックス名;
```

## indexのコメント変更

```
> ALTER TABLE テーブル名
 DROP INDEX インデックス名,
 ADD FULLTEXT INDEX インデックス名 (カラム名) COMMENT "コメント";
-- 例
> ALTER TABLE members 
 DROP INDEX idx_members_id_01, 
 ADD INDEX idx_members_01 (id) COMMENT "HOGE";
```

## データ挿入(INSERT)

[INSERT 構文](https://dev.mysql.com/doc/refman/5.6/ja/insert.html)

```
> INSERT INTO テーブル名 (カラム名) VALUES (値);
-- 例①(全カラムの情報入れる時はカラム名指定いりません、してもいいけど)
> INSERT INTO members 
VALUES
(1, '織田信長', 'nobu_oda@example.com', 'HOGE', '/oda_icon.jpg', '2020-12-02 1:14:22', '2020-12-02 1:14:22');
-- 例②(特定のカラムに情報入れる時)
> INSERT INTO members
(name, email, password, picture, created)
VALUES
('豊臣秀吉', 'hide_toyo@example.com', 'FUGA', '/toyo_icon.jpg', '2020-12-01 10:00:00');
```

## データ行削除(DELETE)

[DELETE 構文](https://dev.mysql.com/doc/refman/5.6/ja/delete.html)

```
> DELETE FROM テーブル名;
-- 例①(全部の行消えます)
DELETE FROM members;
-- 例②(限定したいならWHERE句使うとか)
DELETE FROM members WHERE id=3;
```

## データ選択(SELECT)

[SELECT構文](https://dev.mysql.com/doc/refman/5.6/ja/select.html)

```
> SELECT カラム名, FROM テーブル;
-- 例①特定のカラム
> SELECT id, name FROM members;
-- 例②全てのカラム
> SELECT * FROM members;
-- 例③特定の行のみ
> SELECT * FROM members WHERE id=3;
```

# 筆者が詰まったところ

- `AUTO_INCREMENT`制約のあるカラムには必ずkeyを設定しないといけない

indexを貼ったり、`PRIMARY KEY`の設定をしてやろう

```
CREATE TABLE members (
id INT NOT NULL AUTO_INCREMENT,
name varchar(255)
);
(1075, 'Incorrect table definition; there can be only one auto column and it must be defined as a key')
```

- DROP INDEXが出来ない

`SHOW INDEX`を使って下記のようなインデックスがあることを確認

PRIMARYを消そうとするが...

![drop_target.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403039/c0d739f5-0e62-f973-74cc-b35bf9e37e83.png)

```
> ALTER TABLE members DROP INDEX PRIMARY;
(1064, "You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'PRIMARY ON members' at line 1")
```

主キーのインデックス名が常に PRIMARY である一方でPRIMARY が予約語であるため、引用符で囲まれた識別子として指定しないとエラーになってしまうのが原因です。下記のようにバッククオート``で囲ってやるとうまく行きます。

```
> ALTER TABLE members DROP INDEX `PRIMARY`;
```

ちなみに`AUTO_INCREMENT`が設定されていて一つしかKEYがないカラムのKEYをDROPさせることは出来ません。

## ちょっとした知識まとめ(随時追記予定)

- varchar型のサイズ

```
[NATIONAL] VARCHAR(M) [CHARACTER SET charset_name] [COLLATE collation_name]
```

varcharは可変長の文字列です。(固定長はchar型というのがあります。)上記のMというのは文字列の最大列長を表しており、0から65,532までの範囲を設定...できるのですが有効な最大長は、最大行サイズと使用する文字セットに依存します。

utf-8文字は1文字あたり最大3バイトを必要とするため、utf-8文字セットを使用するVARCHAR列は最大21,844文字と宣言することができます。

※参考

[UTF-8（ユーティーエフエイト）とは？文字コードの仕組みを知れば文字化けでも慌てない](https://ferret-plus.com/7006)

 [VARCHAR / MariaDB公式](https://mariadb.com/kb/en/varchar/)

## 参考サイト

- [mycli公式ドキュメント](https://www.mycli.net/)
- [MyCLI – A MySQL/MariaDB Client with Auto-completion and Syntax-highlighting](https://www.tecmint.com/mycli-mysql-client-with-auto-completion-syntax-highlighting/#:~:text=MyCLI%20is%20an%20easy%2Dto,SSL%20to%20the%20MySQL%20server.))
- [mycli が便利過ぎる - kakakakakku blog](https://kakakakakku.hatenablog.com/entry/2015/09/08/004426)

- [データベースオブジェクトの命名規約 / Qiita記事](https://qiita.com/genzouw/items/35022fa96c120e67c637)

- [MySQLのデータ型 / DBOnline](https://www.dbonline.jp/mysql/type/)

- [第 11 章 データ型 / MySQL公式](https://dev.mysql.com/doc/refman/5.6/ja/data-types.html)