【MySQL】基本的な文法やデータ型についてまとめてみた

# はじめに
MySQLについて学習していて基礎的なことを忘れないように備忘録がてら投稿します。

どなたかのお役に立てれば幸いです。


## データベースの用語

MySQLで登場する用語などについて紹介します。

### TABLE
データベースにデータを格納するわけですが、
データを格納する表のことをTABLEといいます。

下記のTABLEはTwitterの投稿文といいね数を集計したTABLEです。
![スクリーンショット 2021-03-20 16.21.39.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/2679b228-5b17-58ac-62cf-d4f30b538958.jpeg)

# RECORD
データが入っている一行一行のことをRECORDといいます。
![スクリーンショット 2021-03-20 16.21.45.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/c5ae9c09-18ad-9b06-0f2e-020d84b4374e.jpeg)

# CULUMN

逆に列のことをCULUMNといいます。
![スクリーンショット 2021-03-20 16.21.50.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/38706f02-93d9-9ce7-abe4-02088ce4ce8c.jpeg)


## データ型

よく使用するデータ型について記載します。

下記のデータを使った例は下で説明していますので
ぜひそちらをご覧ください。

### 整数

整数には`TINYINT`、`INT`、`BIGINT`の3つがあります。
各型には扱える範囲があります。

| 型 | min| max |
|:-:|:-:|:-:|
|  TINYINT | -128  |  +127 |
|  INT | -21億  | +21億  |
|  BIGINT | -922京  | +922京  |

京なんと単位みたことないですが、
通常はINTで大丈夫だと思います！

今回はマイナスからプラスの範囲で表を作成しましたが、
Twitterのいいねのようにマイナスが存在しない場合は、
データ型に`UNSIGNED`を付けることで扱える範囲の幅を広げることが出来ます。

| 型 | min| max |
|:-:|:-:|:-:|
|  TINYINT UNSIGNED | 0  |  255 |
|  INT UNSIGNED | 0  | +42億  |
|  BIGINT UNSIGNED | 0  | +1844京  |

### 実数

実数には`DECIMAL`、`FLOAT`、`DOUBLE`の3つがあります。

各型については下記のようになります。

| 型 | 説明 |
|:-:|:-:|
| DECIMAL  | 固定小数点  |
| FLOAT  | 浮動小数点  |
| DOUBLE  | 浮動小数点（高精度）  |

**FLOAT**と**DOUBLE**は浮動小数点なので細かいところで誤差が出てきます。
なので、**DECIMAL**を使用してもいいかと思います。

### 文字列

文字列には`CHAR`、`VARCHAR`、`TEXT`、`ENUM`、`SET`の5つがあります。

各型については下記のようになります。

| 型 | 説明 |
|:-:|:-:|
| CHAR  | 0 〜 255文字  |
| VARCHAR  | 0 〜 65535文字  |
| TEXT  | それ以上  |
| ENUM  | 特定の文字列から一つ  |
| SET  | 特定の文字列から複数  |

商品コードなどの固定長のデータには**CHAR**を使い、
文字数がバラバラになるようなデータの場合は**VARCHAR**を使い、
それよりも長くなる文字列には**TEXT**を使用するようなイメージでいいと思います。

**ENUM**は、出身の都道府県を一つ選択する時のような場合に、
**SET**は、アンケートの解答などで複数選択する場合に使ったりします。

### 真偽値

真偽値は`BOOL`のみになります。

BOOLは**TRUE**か**FALSE**を保持することが出来ます。

しかし、内部的にはTRUEが１、FALSEが０と管理されています。
なので、一桁のTINYINTと同じ型だったりします。

### 日時

日時には`DATE`、`TIME`、`DATETIME`の3つがあります。

| 型 | 説明 |
|:-:|:-:|
| DATE  | 日付  |
| TIME  | 時間  |
| DATETIME  | 日時  |

日にちだけなら**DATE**、時間だけなら**TIME**、
両方使いたい場合なら**DATETIME**を使用します。

## コマンド

### TABLEの作成
TABLEを作るには`CREATE TABLE`コマンドで作成します。
`<テーブル名>`には任意の名前を入れてください。

また、コマンドの最後に`;（セミコロン）`を忘れないようにしてください。

```sql
CREATE TABLE <テーブル名>();
```

また、`<テーブル名>()`の`()`には列見出しにあたるCULUMNの名前を定義します。
名前の定義と同時に方の宣言も行います。

`message`というCULUMNに入る値は可変長のCHAR（140文字以下）
`likes`というCULUMNに入る値はINT型（整数）

```sql
CREATE TABLE posts(message: VARCHAR(140), likes INT);
```

コマンドが長くなりそうな場合は行を分けることも可能です。

```sql
CREATE TABLE posts(
  message: VARCHAR(140), 
  likes INT
);
```

これでデータがからのTABLEが作成されます。

### TABLEの構成確認

TABLEがどのような構成かを確認するには`DESC`コマンドを使用します。
`<テーブル名>`には任意のテーブル名が入ります。

```sql
DESC <テーブル名>;
```

先ほど作成したTABLEを確認すると下記のようになります。

```sql
DESC posts;

実行結果
+---------+--------------+------+-----+---------+-------+
| Field   | Type         | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+-------+
| message | varchar(140) | YES  |     | NULL    |       |
| likes   | int(11)      | YES  |     | NULL    |       |
+---------+--------------+------+-----+---------+-------+
```

###存在するテーブルの確認

存在するTABLEの一覧を確認するには`SHOW`コマンドを使用します。
現在はpostsテーブルのみが存在することになります。

```sql
SHOW TABLES;

実行結果
+-----------------+
| Tables_in_myapp |
+-----------------+ 
| posts           |
+-----------------+
```

### TABLEの削除方法

TABLEを削除するには`DROP TABLE`コマンドを使用します。
`<テーブル名>`には任意の値が入ります。

```sql
DROP TABLE <テーブル名>;
```

なと、先ほどのコマンドではテーブルが作成されていない時に実行すると、
**テーブルがありません！！！**というエラーが出てしまうので、
テーブルが存在する時のみ削除を行いたい！という場合は下記のように行います。

`DROP TABLE(テーブルを削除してね) IF（もし） EXISTS（存在したら）`と言ったような具合です。

```sql
DROP TABLE IF EXISTS <テーブル名>;
```

### レコードの挿入

作成したテーブルにレコードを挿入する場合は`INSERT INTO`コマンドを使用します。

テーブル名の後の( )の中には`CULUMN`を記述し、
そのCULUMN名に入れる値をVALUESの後の( )に記述します。

```sql
INSERT INTO <テーブル名>(CULUMN名) VALUES (値);
```

先程のpostsテーブルを使用すると下記のようになります。
postsテーブルは、**message**と**likes**というCULUMN（列）があります。

`posts(message,likes)`-> postsのmessageとlikesに対して、
`VALUES ('Thanks', 12)`-> 'Thanks'と12を格納します。という感じです。

なぜ'Thanks'は`''（シングルクォーテーション）`を使用しているかというと、
テーブル作成の時に`VARCHAR(140)`と宣言しているからです。

ここら辺の`''`を付けるか付けないかの判断は調べてみてください。

なお、テーブルの作成同様に改行しながら記述することが可能になります。

```sql
-- テーブル作成
CREATE TABLE posts (
  message VARCHAR(140), 
  likes INT
);

-- テーブルにデータを格納
INSERT INTO posts(message,likes) VALUES ('Thanks', 12);
INSERT INTO posts(message,likes) VALUES ('Hello', 4);
INSERT INTO posts(message,likes) VALUES 
  ('Sorry!!', 114),
  ('Good morning', 222);
```

### データの取得

テーブルに格納されているデータを取得する場合は`SELECT`コマンドを使用します。

```sql
SELECT <CULUMN名> FROM <テーブル名>;
```

先程のpostsテーブルを例にすると下記のようになります。
下記の場合はmessageのCULUMNに該当する値を取得します。

```sql
SELECT message FROM posts;

実行結果
+--------------+
| message      |
+--------------+
| Thanks       |
| Hello        |
| Sorry!!      |
| Good morning |
+--------------+
```

複数指定する場合は下記のようになります。
`message, likes`のように`,`で区切って指定します。

```sql
SELECT message, likes FROM posts;

実行結果
+--------------+-------+
| message      | likes |
+--------------+-------+
| Thanks       |    12 |
| Hello        |     4 |
| Sorry!!      |   114 |
| Good morning |   222 |
+--------------+-------+
```

全ての値を取得する場合下記のようになります。

```sql
SELECT * FROM posts;

実行結果
+--------------+-------+
| message      | likes |
+--------------+-------+
| Thanks       |    12 |
| Hello        |     4 |
| Sorry!!      |   114 |
| Good morning |   222 |
+--------------+-------+
```

## 各データ型の使い方

`INT`と`VARCHAR`は先ほどから使用していたので、
それ以外について軽く説明していきます。

### 数値・文字列

先ほどまでのpostsを少しいじってみました。

`likes INT UNSIGNED`ですが、
Twitterのいいねはマイナスが存在しないので、`UNSIGNED`を付けました。
これにより、0以上の値しか格納出来なくなります。

`mood DECIMAL(4, 2) UNSIGNED`は、実数の中の固定小数点でしたね！
`DECIMAL(4, 2)`という部分ですが、４桁の実数で小数点２桁まで表示という意味になります。

つまり、`12.34`なら全て表示されますが、`1.234`なら`1.23`までしか表示されません。

`lang CHAR(2)`ですが、二文字の文字列しか入れることが出来ません。
言語などを選択する時は２桁だったりするので、そう言った場合に使うことが出来ます。

```sql
DROP TABLE IF EXISTS posts;
CREATE TABLE posts (
  message VARCHAR(140), 
  likes INT UNSIGNED, 
  mood DECIMAL(4, 2) UNSIGNED,
  lang CHAR(2)
);

INSERT INTO posts (message, likes, mood, lang) VALUES
  ('Thanks', 12, 7.453, 'JP'), 
  ('Arigato', 4, 3.439, 'EN');

SELECT * FROM posts;

実行結果
+---------+-------+------+------+
| message | likes | mood | lang |
+---------+-------+------+------+
| Thanks  |    12 | 7.45 | JP   |
| Arigato |     4 | 3.44 | EN   |
+---------+-------+------+------+
```

### ENUM

先程のpostsは一旦元に戻してENUMについて説明します。

ENUM型は**複数の値の中から一つを選ぶ型**でした。

テーブルを作成する際に
`category ENUM('Gadget', 'Game', 'Business')`のように
複数の選択肢を用意します。

そのテーブルにデータを格納する場合は、
ENUMの中から一つを選択しなければなりません。

つまり、`('Thanks', 12, 'Game'),`のようになります。

なお、ここでENUMで定義されているもの以外を格納しようとするとエラーが発生します。

```sql
DROP TABLE IF EXISTS posts;
CREATE TABLE posts (
  message VARCHAR(140), 
  likes INT,
  category ENUM('Gadget', 'Game', 'Business')
);

INSERT INTO posts (message, likes, category) VALUES 
  ('Thanks', 12, 'Game'),
  ('Arigato', 4, 'Gadget'),
  ('Arigato', 4, 'Business');

SELECT * FROM posts;

実行結果
+---------+-------+----------+
| message | likes | category |
+---------+-------+----------+
| Thanks  |    12 | Game     |
| Arigato |     4 | Gadget   |
| Arigato |     4 | Business |
+---------+-------+----------+
```

ついでですが、データを格納する時は下記のように記述することも可能です。

`ENUM('Gadget', 'Game', 'Business')`に対して、
１番目の値、２番目の値、３番目の値と指定することが出来ます。

つまり、`('Thanks', 12, '2')`は２番目の**Game**が格納されます。

```sql
DROP TABLE IF EXISTS posts;
CREATE TABLE posts (
  message VARCHAR(140), 
  likes INT,
  category ENUM('Gadget', 'Game', 'Business')
);

INSERT INTO posts (message, likes, category) VALUES 
  ('Thanks', 12, '2'),
  ('Arigato', 4, '1'),
  ('Arigato', 4, '3');

SELECT * FROM posts;

実行結果
+---------+-------+----------+
| message | likes | category |
+---------+-------+----------+
| Thanks  |    12 | Game     |
| Arigato |     4 | Gadget   |
| Arigato |     4 | Business |
+---------+-------+----------+
```

### SET

SET型は**複数の値の中から複数を選択することができる型**でした。

つまり下記のようになります。

`SET('Gadget', 'Game', 'Business')`は
ENUMだった箇所をSETに変更するだけで大丈夫です。

データを格納する際に`('Thanks', 12, 'Gadget,Game')`のように
複数の値を指定することが出来ます。



```sql
DROP TABLE IF EXISTS posts;
CREATE TABLE posts (
  message VARCHAR(140), 
  likes INT,
  categories SET('Gadget', 'Game', 'Business')
);

INSERT INTO posts (message, likes, categories) VALUES 
  ('Thanks', 12, 'Gadget,Game'),
  ('Arigato', 4, 'Business'),
  ('Merci', 4, 'Business,Gadget');
  
SELECT * FROM posts;

実行結果
+---------+-------+---------------+
| message | likes | categories    |
+---------+-------+---------------+
| Thanks  |    12 | Gadget,Game   |
| Arigato |     4 | Business      |
| Merci   |     4 | Game,Business |
+---------+-------+---------------+
```

また、SET型もENUM型と同様に数字で格納することが出来ます。

数字の場合は次のようになります。
`('Merci', 4, 6)`って、`6`はどこから出たんだ！と思いますが、
SET型は複数選ぶことができるので、選びたい項目の合計を記載します。

そして、各項目の値は次のようになります。

| 1番目(Gadget) | 2番目(Game) | 3番目(Business) | ・・・ | n番目 |
|:-:|:-:|:-:|:-:|:-:|
| 2^0  | 2^1  | 2^2  | ・・・  | 2^n  |

なので、Gadgetは**２の０乗**で**１**になります。
Gameは**２の１乗**で**２**にBusinessは**２の２乗**で**４**です。
（ここら辺がわからない型は少し数学を復習してください・・・。）

`Gadget`と`Game`を選ぶ場合は、
1つ目と2つ目なので、**１＋２＝３**つまり３を記述します。


```sql
DROP TABLE IF EXISTS posts;
CREATE TABLE posts (
  message VARCHAR(140), 
  likes INT,
  categories SET('Gadget', 'Game', 'Business')
);

INSERT INTO posts (message, likes, categories) VALUES 
  ('Thanks', 12, 3),
  ('Arigato', 4, 4),
  ('Merci', 4, 6);

SELECT * FROM posts;

実行結果
+---------+-------+---------------+
| message | likes | categories    |
+---------+-------+---------------+
| Thanks  |    12 | Gadget,Game   |
| Arigato |     4 | Business      |
| Merci   |     4 | Game,Business |
+---------+-------+---------------+
```

### 真偽値・日時

次にBOOL（真偽値）とDATETIME（日時）です。

BOOLは**真（TRUEもしくは１）**か**偽（FALSEもしくは０）**を格納すればOKです。

DATETIMEは、`'2020-10-11 15:33:22'`のように
日にちと時間を指定しても構いませんし、
`'2020-10-21'`のように時間を指定せず日にちのみでも構いません。
ただ、時間を記述しない場合は`00:00:00`が格納されます。

また、`NOW()`と記述すると現在の日時が格納されます。

```sql
DROP TABLE IF EXISTS posts;
CREATE TABLE posts (
  message VARCHAR(140), 
  likes INT,
  is_draft BOOL,
  created DATETIME
);

INSERT INTO posts (message, likes, is_draft, created) VALUES 
  ('Tnanks', 12, TRUE, '2020-10-11 15:33:22'),
  ('Arigato', 4, FALSE, '2020-10-21'),
  ('Merci', 4, 0, NOW());

SELECT * FROM posts;

実行結果
+---------+-------+----------+---------------------+
| message | likes | is_draft | created             |
+---------+-------+----------+---------------------+
| Tnanks  |    12 |        1 | 2020-10-11 15:33:22 |
| Arigato |     4 |        0 | 2020-10-21 00:00:00 |
| Merci   |     4 |        0 | 2021-03-20 17:55:21 |
+---------+-------+----------+---------------------+
```

# さいごに
基本的な文法やデータ型については以上になります。

もう少し踏み込んだ内容についても乗せていますのでぜひご覧ください。
・[【MySQL】少し踏み込んだMySQLの基本的な文法](https://qiita.com/Kai_82/items/b990f0180e696eb3d40f)


以上、最後までご覧いただきありがとうございました。