SQLの命令文 ~基本編~

今回は、主に四大命令（SELECT,INSERT,UPDATE,DELETE）を中心に、基本的なSQL命令文をご紹介します。

# DDL(Data Definition Language)
データ定義言語：テーブルなどの作成や削除、各種設定などの命令を行う。

## CREATE
データベース、テーブルを作成するための命令文

### データベースの作成
```sql
CREATE DATABASE データベース名;
```
### テーブルの作成
```sql
CREATE TABLE テーブル名 (
  カラム名 データ型 制約,
  カラム名 データ型 制約,
);
```

### データ型
データ型とは、カラムに保存するデータの種類や形式を定義し、フォーマットを揃えるために指定するものです。

#### 数値を扱うデータ型
|データ型|説明|
|---|---|
|INTEGER|整数型を表す|
|DECIMAL|浮動小数点を表す|
|FLOAT|小数第7位程度まで格納する浮動小数点を表す|
|DOUBLE|小数第15位程度まで格納する浮動小数点を表す|
|SERIAL|連番の整数系を表す|

#### 文字列を扱うデータ型
|データ型|説明|
|---|---|
|CHAR(n)|固定長の文字列を保存します。nは文字列の最大長を指定します。|
|VARCHAR(n),<br>CHARACTER VARYING(n)|可変長の文字列を保存します。nは文字列の最大長を指定します。|
|TEXT|非常に大きな可変長の文字列を保存します。|

#### 日付や時間を扱うデータ型
|データ型|説明|
|---|---|
|DATE|日付を保存する|
|TIME|時刻を保存する|
|DATETIME|日付と時刻の両方を保存する|
|TIMESTAMP|日付と時刻の両方を保存しますが、特定のイベントが発生した日時を格納するのに使用されます。|

#### BOOLEAN型
BOOLEAN型は、「真（true）」と「偽（false）」の２種類の値のみを扱うデータ型です。

### 制約
制約とは、カラムに対して適用される条件や規則のことです。
制約をつけて格納できるデータに制限をかけたりすることで、データの整合性を保ち、不正なデータの挿入や変更を防ぐことができます。
|制約|説明|
|---|---|
|NOT NULL|NULLの格納が許可されません。列には NULL 値を挿入することができず、列に必ず値が入ることが保証されます。|
|UNIQUE|他の行と同じ値を入れられないようにする制約がUNIQUEです。もし重複した値を格納しようとした場合はエラーとなって登録ができません。|
|CHECK|CHECK(条件式)のように記述でき、カッコ内の条件式が真となる値だけが書くのされます。|
|PRIMARY KEY|主キーとしての制約を定義します。NULLが入ることはなく、同じ値が入ることもありません。連番設定で用いられることが多いです。|
|FOREGN KEY|外部キー制約を定義し、他のテーブルの主キーとの関連性を保証します。関連するテーブル間のデータ整合性を維持することができます。|
|DEFAULT|DEFAULT制約を使うとカラムに初期値を設定することができます。|

### テーブル作成の例
```sql
CREATE TABLE users (
  id serial NOT NULL,
  name character varying(20) NOT NULL,
  age integer DEFAULT 0 CHECK (age >= 0),
  PRIMARY KEY (id)
);
```
usersテーブルにid,name,ageのカラムを設定します。
idは主キーに設定し、ageはデフォルトで0が入り、0以上の数値が格納されるようになっています。


## ALTER
テーブル構造の変更を行う命令文

### テーブル名の変更
```sql
ALTER TABLE 現在のテーブル名 RENAME TO 新しいテーブル名;
```

### カラムの追加
```sql
ALTER TABLE 対象のテーブル名 ADD COLUMN 追加するカラム名 データ型;
```

### カラムの削除
```sql
ALTER TABLE 対象のテーブル名 DROP COLUMN 削除したいカラム名;
```

### カラム名の変更
```sql
ALTER TABLE 対象のテーブル名 RENAME COLUMN 現在のカラム名 TO 新しいカラム名;
```

### カラムへの制約追加
```sql
ALTER TABLE 対象のテーブル名 ALTER COLUMN 対象のカラム名 SET 追加したい制約;
```

### デフォルト値の追加
```sql
ALTER TABLE 対象のテーブル名 ALTER COLUMN 対象のカラム名 SET DEFAULT デフォルト値;
```


## TRUNCATE
テーブルを初期化するための命令文
実行結果は`DELETE FROM テーブル名`とほぼ同じですが、以下のような違いがあります。
- DELETEは記録を残しながら仮削除するためロールバックできるが、TRUNCATEはロールバックできない
- DELETEは低速だが、TRUNCATEは高速

※ロールバック・・・トランザクション処理において、途中でエラーが発生した場合や不具合が起こった場合に、処理前の状態に戻すことを指します。
処理が失敗した場合に前の状態に「ロールバック」することで、不正確なデータを残すことなく正確なデータを保持することができます。
```sql
TRUNCATE TABLE 空にしたいテーブル名;
```

### 連番のリセット
`id`を`serial`型のカラムに設定していると、データの挿入を行うと自動的に連番が割り振られます。
`TRUNCATE`文でテーブルを空にしても、次にデータを挿入した時には「1」からではなく、一番最後に挿入したデータの次の番号が割り振られます。
下記のコードは、連番をリセットして再度「1」から割り振ります。
```sql
TRUNCATE TABLE 対象のテーブル名 RESTART IDENTITY;
```

## DROP
テーブルの削除を行う命令文
DROPは基本的にロールバッグできず、一度実行すると取り消しができません。万が一に備え、テーブルを削除する場合などは、バックアップをしておきましょう。
```sql
DROP TABLE 削除したいテーブル名;
```


# DML(Data Manipulation Language)
データ操作言語: データの格納や取り出し、更新、削除などの命令を行います。
四大命令はこの中に分類されます。

## SELECT
テーブルからデータを選択・取得する
```sql
SELECT
  カラム名1,
  カラム名2,
FROM
  テーブル名
;
```
例：`users`テーブルから`name`と`age`を選択して取得する
```sql
SELECT
  name,
  age
FROM
  users
;
```
例：すべてのカラムを選択したい場合には`アスタリスク(*)`を利用します。
```sql
SELECT
  *
FROM
  users
;
```

### 条件付きの選択 WHERE
条件を絞って特定のデータのみ取得する
```sql
SELECT
  カラム名1,
  カラム名2,
FROM
  テーブル名
WHERE
  条件式
;
```
例：名前がyamadaのユーザーを選択して取得する
```sql
SELECT
  *
FROM
  users
WHERE
  name = 'yamada'
;
```

### 複数の条件を設定する
例：名前がyamada、かつ年齢が30歳以上のユーザーを選択する
```sql
SELECT
  *
FROM
  users
WHERE
  name = 'yamada'
  AND age >= 30
;
```
例：年齢が20歳、または30歳のユーザーを選択する
```sql
SELECT
  *
FROM
  users
WHERE
  age = 20
  OR age = 30
;
```
例：年齢が20歳から25歳の範囲のユーザーを選択する
```sql
SELECT
  *
FROM
  users
WHERE
  age BETWEEN 20 AND 25
;
```

### 比較演算子
|演算子|説明|
|---|---|
|=|等しいことを比較する|
|<>または!=|等しくないことを比較する|
|<|小なりを比較する|
|>|大なりを比較|
|<=|小なりイコールを比較|
|>=|大なりイコールを比較|
|IS NULL|NLL値であることを比較|
|IS NOT NULL|NULL値でないことを比較する|
|BETWEEN|範囲内に存在することを比較する|
|NOT BETWEEN|範囲内に存在しないことを比較|
|LIKE|文字列の一部がパターンに一致するかを比較|
|NOT LIKE|文字列の一部がパターンに一致しないことを比較|
|IN|指定した値のいずれかと一致するかを比較|
|NOT IN|指定した値のいずれとも一致しないかを比較|

例：年齢が20、25、30に一致するユーザーを選する
```sql
SELECT
  *
FROM
  users
WHERE
  age IN(20, 25, 30)
;
```
`IN`は比較したい値をカンマ区切りで記述することで、一致するものだけ選択することができます。

例：名前がNULLのユーザーを選択したい
```sql
SELECT
  *
FROM
  users
WHERE
  name IS NULL
;
```
逆にNULL以外のデータを選択したい場合は、`IS NOT NULL`と記述するだけで選択することが可能です。

例：名前がyamaから始まるユーザーを選択したい
```sql
SELECT
  *
FROM
  users
WHERE
  name LIKE 'yama%'
;
```
`LIKE`は値の一部が一致するデータを選択したい場合に利用します。

ワイルドカード（%、_）のパターン
- ％は、任意の0文字以上の文字列があった場合
- _は、任意の1文字の時のみ


||山|山野辺|有馬山|金山沢|山田|
|---|---|---|---|---|---|
|山%|◯|◯|×|×|◯|
|%山|◯|×|◯|×|×|
|%山%|◯|◯|◯|◯|◯|
|山_|×|×|×|×|◯|

## INSERT
テーブルに新しいデータを追加するための命令文
```sql
INSERT INTO
  テーブル名 (カラム名1, カラム名2, ...)
VALUES
  (値1, 値2, ...)
;
```
例：`id`カラムに「1」、`name`カラムに「yamada」、`age`カラムに「22」というデータを挿入する
```sql
INSERT INTO
  users (name, age)
VALUES
  ('yamada', 22)
;
```
例：複数件データを挿入する
```sql
INSERT INTO
  users (name, age)
VALUES
  ('tanaka', 30),
  ('sato', 33)
;
```

## UPDATE
テーブルに存在するデータを書き換えるための命令文
```sql
UPDATE
  テーブル名
SET
  変更したいカラム名 = 新しい値
WHERE
  条件式
;
```
`WHERE`を利用することで更新対象を絞り込んでデータの更新が行えます。

例：`employees`テーブルの`id`が5の岩本さんの年齢を21歳に変更する
```sql
UPDATE
  employees
SET
  age = 21
WHERE
  id = 5
;
```
例：複数のカラムの値を更新したい場合
```sql
UPDATE
  employees
SET
  age = 22,
  department_id = 2
WHERE
  id = 5
;
```
**データの更新を行う場合には、基本的に`WHERE`で対象となるレコードを絞り込んだ上で実行します。`WHERE`で条件を指定せずに実行してしまうと、テーブル内の全てのデータが更新されてしまいます。**

## DELETE
テーブルに存在するデータを削除するための命令文
```sql
DELETE
FROM
  テーブル名
WHERE
  条件式
;
```
`UPDATE`文と同様に、`WHERE`を利用することで対象を絞り込んだ上でデータの削除を行うことができます。

例：`employees`テーブルの`id`が5のデータを削除する場合
```sql
DELETE
FROM
  employees
WHERE
  id = 5
;
```