MySQL 入門

## あらすじ

WEB系のフロントエンジニアがこれから MySQL を勉強しようとしているがそもそも SQL がよくわからないので最低限の操作を覚える必要があるとかないとか。

私の経験を元に、最初に覚えておいたほうがいい事をまとめました。とはいえ最初にどこでつまづいたのか若干記憶が遠のいているのでニーズを満たせるかどうかよくわかっていません。

## 準備

MacOSX の場合は以下で MySQL が使えるようになります。`brew` を使った事はないという方は Google にて検索してください。あと Windows ユーザーの人も自力でなんとかしてください。

```
% brew install mysql
```

version を確認します。私の手元では `5.7.17` となっていました。 もし version が異なる場合は `brew upgrade mysql` で最新版に変更できます。

```mysql
% mysql --version
```
                                                                                  
## start, stop

MacOSX で `brew install mysql` した場合は以下で start, stop ができます。`mysql.server status` で動いているかどうかを確認することができます。

```
mysql.server start
mysql.server stop
```

## 01: MySQL と対話する

デフォルトだと root ユーザーの場合 nopassword でログインできると思います。

```sh
mysql -u root
```

ターミナルに以下のような画面がでれば MySQL と対話できる状態です

```mysql
mysql> 
```

すでに作成されている database 一覧を表示します。

```mysql
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.00 sec)
```

とりあえず `use mysql;` を実行してみましょう。

```mysql
mysql> use mysql;
Database changed
```

`use mysql` の状態で `show tables;` を実行してみましょう。

```mysql
mysql> show tables;
省略
31 rows in set (0.00 sec)
```

上記テーブル一覧に `user` があるのでそれを見てみましょう。

```mysql
mysql> select Host, User from user;
+-----------+-----------+
| Host      | User      |
+-----------+-----------+
| localhost | mysql.sys |
| localhost | root      |
+-----------+-----------+
2 rows in set (0.00 sec)
```

表示するカラムを `Host, User` だけにしているのでシンプルです。全てのカラムを表示したい場合は `*` アスタリスクをつけます

```mysql
select * from user;
```

そうすると横幅が長すぎて見えづらいかと思います。末尾の `;` をセミコロンを `\G` に置き換えると少しみやすくなります。

```mysql
select * from user\G
```

`exit;`　を実行すると対話モードを終了する事ができます。

```mysql
mysql> exit;
```

## 02: MySQL への命令をコマンドラインで実行する

以下のようにコマンドラインへ直接命令を書いたりできます。

```
mysql -u root mysql -e 'show tables;'
```

もしくは命令文をファイルに保存してそれを実行する事ができます。以下のように`show tables;` と1行だけ書かれたファイルを保存します。

```shell-session
% cat example.sql
show tables;
```

以下のコマンドを実行して動作を確認してください。

```
mysql -u root mysql < example.sql
```

## 03: 練習用の Database をつくる

以下のコマンドで練習用の database を作ります。

```
mysql -u root -e 'create database mydb'
```

以下のコマンドで `mydb` との対話モードを開始できます。

```
mysql -u root mydb;
```

## 04: 練習用の Table をつくる

とりあえずドリルなので適当にテーブルを作成してみます。下記のような `scheme.sql` ファイルを作成してください。


```mysql
DROP TABLE IF EXISTS todos;
CREATE TABLE `todos` (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `title` varchar(100) NOT NULL,
  `status` int(1) DEFAULT '0',
  `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
```

以下のコマンドを実行すると todos テーブルを何度でも作り直す事ができます。

```sh
mysql -u root mydb < schema.sql 
```

## 05: 行を追加、参照、更新、削除

行を追加

```mysql
mysql> INSERT INTO todos (title, status) VALUES ("買い物", 1);
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO todos (title, status) VALUES ("料理", 0);
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO todos (title, status) VALUES ("粗大ゴミ", 0);
Query OK, 1 row affected (0.01 sec)
```

参照

```mysql
mysql> select * from todos;
+----+--------------+--------+---------------------+---------------------+
| id | title        | status | created             | updated             |
+----+--------------+--------+---------------------+---------------------+
|  1 | 買い物       |      1 | 2017-04-06 13:36:00 | 2017-04-06 13:36:00 |
|  2 | 料理         |      0 | 2017-04-06 13:36:00 | 2017-04-06 13:36:00 |
|  3 | 粗大ゴミ     |      0 | 2017-04-06 13:36:01 | 2017-04-06 13:36:01 |
+----+--------------+--------+---------------------+---------------------+
3 rows in set (0.00 sec)
```

完了していないタスクを絞り込んで参照

```mysql
select * from todos where status = 0;
+----+--------------+--------+---------------------+---------------------+
| id | title        | status | created             | updated             |
+----+--------------+--------+---------------------+---------------------+
|  2 | 料理         |      0 | 2017-04-06 13:36:00 | 2017-04-06 13:36:00 |
|  3 | 粗大ゴミ     |      0 | 2017-04-06 13:36:01 | 2017-04-06 13:36:01 |
+----+--------------+--------+---------------------+---------------------+
2 rows in set (0.00 sec)
```

料理を終えたのでタスクを更新。

```mysql
mysql> select * from todos where id = 2;
mysql> update todos set status = 1 where id = 2;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0
```

削除したい場合は以下

```mysql
mysql> select * from todos where id = 2;
mysql> delete from todos where id = 2;
```

`where id = 2` を忘れてしまうと全部の行が更新されるので注意しましょう。最初に select 文で where区を確認してからそのクエリの where 区に構文を足すようにすると間違いがないと思います。

## 06: バックアップとリストア

dump.sql にこれまでの作業を保存します。

```sh
% mysqldump -u root mydb > dump.sql 
```

間違えてレコードを全て消してしまったとします。where 句を忘れてしまった場合。

```mysql
mysql -u root mydb -e 'delete from todos'
mysql -u root mydb -e 'select count(*) from todos' 
+----------+
| count(*) |
+----------+
|        0 |
+----------+
```

先ほどの `dump.sql` を使ってリストアします。

```
mysql -u root mydb < dump.sql  
```

無事復元できました。

```mysql
mysql -u root mydb -e 'select count(*) from todos'
+----------+
| count(*) |
+----------+
|        2 |
+----------+
```

## 06: pager の設定

mysql.user の全カラムが全て展開されると画面が崩れて見辛い場合、`\G` を使う方法を紹介しましたが pager を指定する方法もあります。

```sh
mysql> pager less 
PAGER set to 'less -S'
```

この状態で下記コマンドを実行して十字キーで移動してみてください。

```mysql
select * from mysql.user;
```

この `less -S` をやめたい場合は下記のコマンドを実行してください

```
mysql> nopager
PAGER set to stdout
```

またこのように長い画面をコピペしたい場合があると思いますがターミナルだと、どうしていいかわからない事もあるでしょう。その場合は出力先をファイルにして後で使いやすいエディタで開くという方法もあります。

```
mysql> pager cat > output.txt
PAGER set to 'cat > output.txt'
mysql> select * from mysql.user;
2 rows in set (0.00 sec)
mysql> nopager
PAGER set to stdout
```

## 07: 表示形式を CSV にする

時々 MySQL からデータを取り出して欲しいと依頼されたエンジニアが以下のような形式で非エンジニアの依頼者にそのまま渡すケースが見受けられます。

よくよく聞くとCSVデータが欲しいがエンジニアが忙しそうなので自分で頑張ってCSV化していたりする可能性があります。

```mysql
% mysql -u root mydb -e 'select * from todos;'
+----+--------------+--------+---------------------+---------------------+
| id | title        | status | created             | updated             |
+----+--------------+--------+---------------------+---------------------+
|  1 | 買い物       |      1 | 2017-04-06 13:36:00 | 2017-04-06 13:36:00 |
|  3 | 粗大ゴミ     |      0 | 2017-04-06 13:36:01 | 2017-04-06 13:36:01 |
+----+--------------+--------+---------------------+---------------------+
```

もしそういう場面に遭遇した場合は、やり方は以下に載っているので参考にしてみてください。

http://qiita.com/tasmas256/items/ec7e23278ee2b40aad79

もしくは MySQL Workbench などのツールを使ってもよいと思います。

<img width="1303" alt="スクリーンショット 2017-04-06 14.34.25.png" src="https://qiita-image-store.s3.amazonaws.com/0/27622/e7792b48-bf2d-c604-dc5b-6d80bec088ac.png">

## まとめ

pager　と表示形式に関しては最初は気にしなくてもいいと思いますがとりあえず頭の片隅においておくといいのかなあと思います。おしまい。