はじめに
これまでSQLはProgateで軽く触れたくらいでほぼわかっていない状態でした。
プログラミング言語かどうかと言うのすらわかっていなかったです。
今回スッキリわかるSQL入門を読み、調べたりアウトプットしたりをしたので感想と学んだことをまとめてみました。
※SQLは種類によって入力する内容が異なる所がありますが、この記事ではPostgreSQL想定で書いています。
良かったところ
- SQLでテーブルを使う側→テーブルを作る側の順序で書いてあるのでわかりやすくイメージがしやすかった
- 特にSQLのことがわかっていない状態で最初からテーブルや列を作成して、そこに〇〇を書いてと言う流れだと、なぜこれを今作成しているのかと言う状態になってしまっていたかもしれない
- 網羅的にSQLの紹介をしてくれているので一通りの作成手順、作成に必要な操作を学べた
- テーブルというものが存在していてその内容を見るためには、こういう操作をすると言う説明から入ってくれたのでSQLで行う事はこういうことなんだなというイメージがついた
学んだこと
データ操作言語(DML)
- SELECT:内容の取得
- INSERT:新規内容の挿入
- UPDATE:内容の更新
- DELETE:内容の削除
- EXPLAIN
- LOCK TABLE
- 4大命令に以下のものをつけて修飾することで情報を絞っていく
WHERE:処理の対象行の絞り込み
GROUP BY:グループごとに分ける
HAVING:集計した結果をさらに絞り込み
ORDER BY:並び替え
集計関数:SUM, COUNT, AVG, MAX, MIN
※これ以外にも記載できる内容はありますが、ここでは割愛いたします
例
SELECT population
FROM world
WHERE name = 'Germany'
このように記載すると、worldテーブルのGermanyという国からpopulationの情報が取得できます。
トランザクション制御言語(TCL)
- COMMIT
- ROLLBACK
- SET TRANSACTION
- SAVEPOINT
- トランザクションとは、トランザクションに含まれている複数のSQL文が「すべて実行されている」か「すべて実行されていない」のどちらかの状態になるように制御されている仕組み
- トランザクションが実行されると、仮の状態として管理されてすべて実行完了した時点で完了(コミット)となる。途中で処理が終わってしまった場合は、仮の状態が全てなかったことになる(ロールバック)
例
- トランザクションが実行されると、仮の状態として管理されてすべて実行完了した時点で完了(コミット)となる。途中で処理が終わってしまった場合は、仮の状態が全てなかったことになる(ロールバック)
BEGIN;
UPDATE Products
SET stock = stock - 1
WHERE product_id = 5
AND stock >= 1;
INSERT INTO Orders (user_id, product_id, quantity, order_date)
VALUES (2, 5, 1, CURRENT_DATE);
COMMIT;
このようなSQL文があったとして最後まで実行されないとCOMMITがされない
→COMMITされないと全て無かったことになる(ROLLBACK)
データ定義言語(DDL)
- 正規化という作業を行うことでテーブルを作成できる状態にする
- 非正規形、第1正規形、第2正規形、第3正規形、第4正規形、第5正規形まである
- 正規化完了後、以下の入力を使ってテーブルを作成できる
- CREATE
- ALTER
- DROP
- TRUNCATE
例
CREATE TABLE Users (
user_id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
name VARCHAR(50) NOT NULL,
address TEXT,
email VARCHAR(255) UNIQUE NOT NULL
);
CREATE TABLE Orders (
order_id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
user_id INTEGER NOT NULL,
order_date DATE DEFAULT CURRENT_DATE,
CONSTRAINT fk_orders_user_id
FOREIGN KEY (user_id)
REFERENCES Users(user_id)
);
CREATE TABLE Products (
product_id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
title VARCHAR(100) NOT NULL,
author VARCHAR(100) NOT NULL,
price INTEGER CHECK(price >= 0) NOT NULL,
inventory INTEGER CHECK(inventory >= 0) NOT NULL
);
CREATE TABLE OrderDetails (
order_detail_id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
order_id INTEGER NOT NULL,
product_id INTEGER NOT NULL,
quantity INTEGER NOT NULL CHECK(quantity >= 0),
CONSTRAINT fk_order_details_order_id
FOREIGN KEY (order_id)
REFERENCES Orders(order_id),
CONSTRAINT fk_order_details_product_id
FOREIGN KEY (product_id)
REFERENCES Products(product_id)
);
長々と書いてしまいましたが、テーブルを作成するのみであれば下記だけでも可能です。
※Usersの場合
CREATE TABLE Users (
user_id INTEGER,
name VARCHAR(50),
address TEXT,
email VARCHAR(255)
);
列の名前と型を決めています。これ以外は修飾として必要そうなものをつけている状態です。
補足として下記に記載しました。
- user_idなどで連番を作成する際、
SERIALを入力すると自動で番号を入れてくれる
※SQL入門では上記のように書かれていましたが、現在はGENERATED BY DEFAULT AS IDENTITYと記載する方が推奨されているようなので上ではGENERATED〜を記載しています。 - 各列ごとに必要であれば制約を付与する
-
PRIMARY KEY:主キーの設定。NULLも重複も許さない列になる -
NOT NULL:NULLを許さない列になる -
UNIQUE:重複を許さない列になる -
CHECK:記述した条件が真でない場合は格納が許されなくなる-
price INTEGER CHECK(price >= 0)だと、priceに0未満の値を入れることが許されなくなる
-
-
-
DEFAULTと記載すると、その列の初期値を設定することができる- order_dateに
DEFAULT CURRENT_DATEと記載しておくと、注文があった際に現時点の日付をデフォルトで入力してくれる
- order_dateに
- 外部キー制約(上に記載したOrdersの簡略版)
- 参照整合性が崩れるようなデータ操作をしようとした場合にエラーを発生させ、強制的に処理を中断させる制約
CREATE TABLE Orders (
user_id INTEGER,
FOREIGN KEY (user_id)
REFERENCES Users(user_id)
);
Ordersテーブルのuser_idは、Usersテーブルのuser_idを参照していると言う意味になる。
その状態でUsersテーブルのuser_idを削除しようとするとエラーが発生して削除できない。
そのおかげで参照整合性が崩れないようになる。
また、FOREIGN KEYの上にCONSTRAINTを記載すると、その後に書いた文言を外部キー制約の名前にすることができる。
CREATE TABLE Orders (
user_id INTEGER,
CONSTRAINT fk_orders_user_id ←この文を追記したのみ
FOREIGN KEY (user_id)
REFERENCES Users(user_id)
);
データ制御言語(DCL)
- GRANT:権限を付与
- REVOKE:権限を剥奪
- 誰にどのようなデータ操作やテーブル操作を許すかといった権限を設定するための内容
- 特に今回出番なし
難しかったこと
情報を取得するときにWHEREやGROUP BYに書いて良いものの判別が難しかったです。
今もまだ曖昧ですが、しっかり使えるようにアウトプットを引き続き行います。