Day10 前半のゴール
「ビューを“保存されたSELECT文”としてイメージできるようになる」
Day10 のテーマはビュー(VIEW)です。
SQLite にもビューはありましたが、使わずに来た人も多いはずです。
まず押さえたいのは、この一言です。
ビュー=「名前を付けて保存したSELECT文」
テーブルのように SELECT * FROM xxx で読めるけれど、
中身は実体のあるデータではなく「元テーブルへの問い合わせ」です。
Day10 前半のゴールは、
CREATE VIEW の基本的な書き方を理解する
ビューを「複雑なSELECTに名前を付けたもの」としてイメージできる
どんな場面でビューを使うと嬉しいか、ざっくり分かる
ここまで行ければ、後半の「制限」「更新可能ビュー」の話が入ってきます。
ビューとは何か
「“よく使うSELECT”にショートカットキーを付けるイメージ」
まずはイメージからいきます。
テーブル
実際のデータが入っている箱
ビュー
テーブルに対するSELECT文に名前を付けた“仮想テーブル”
ビュー自体はデータを持ちません。
「このビューをSELECTしたら、裏でこのSELECT文を実行してね」という“定義”だけを持っています。
たとえば、毎回こんなSELECTを書いているとします。
SELECT
u.id,
u.name,
o.id AS order_id,
o.total
FROM users u
JOIN orders o
ON o.user_id = u.id;
SQLこれをビューにしてしまえば、
SELECT * FROM user_orders;
SQLのように、短く・分かりやすい名前で呼び出せるようになります。
CREATE VIEW の基本構文
「SELECT に名前を付けるだけ、と考える」
ビューの作り方はとてもシンプルです。
CREATE VIEW ビュー名 AS
SELECT文...;
SQLさっきの例をビューにすると、こうなります。
CREATE VIEW user_orders AS
SELECT
u.id AS user_id,
u.name AS user_name,
o.id AS order_id,
o.total AS order_total
FROM users u
JOIN orders o
ON o.user_id = u.id;
SQLこれで、
SELECT *
FROM user_orders
WHERE user_id = 1;
SQLのように、テーブルと同じ感覚で使えます。
重要なのは、
ビューは「SELECT文を保存したもの」であって、
その時点でデータをコピーしているわけではない
という点です。
元の users / orders が更新されれば、
ビューから見える内容も自動的に変わります。
ビューを使うと何が嬉しいか
「複雑さを隠す・名前で意味を表現する」
ビューの一番のメリットは、
「複雑なSELECTの中身を隠して、意味のある名前で扱える」ことです。
例えば、
ユーザーとその最新注文をJOINした複雑なSELECT
売上集計をいろいろ計算しているSELECT
セキュリティ的に見せてよいカラムだけを選んだSELECT
こういったものに active_users や monthly_sales のような名前を付けておけば、
アプリ側や他の開発者は「中身のSQLを知らなくても使える」ようになります。
これは、
コードでいう「関数」
オブジェクト指向でいう「メソッド」
に近い役割です。
内部の実装(SELECT文)はビューの定義に閉じ込めておき、
外からは「ビュー名」というインターフェースだけを使う、という設計ができます。
具体例:アクティブユーザーのビュー
「WHERE 条件をビューに閉じ込める」
例えば、「アクティブユーザー」をこう定義するとします。
退会フラグが立っていない
メールアドレスが確認済み
テーブルがこうだとします。
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
email VARCHAR(255) NOT NULL,
is_deleted TINYINT(1) NOT NULL DEFAULT 0,
email_verified TINYINT(1) NOT NULL DEFAULT 0
) ENGINE=InnoDB;
SQLアクティブユーザーだけを取るSELECTはこうです。
SELECT
id,
name,
email
FROM users
WHERE is_deleted = 0
AND email_verified = 1;
SQLこれをビューにしてしまいます。
CREATE VIEW active_users AS
SELECT
id,
name,
email
FROM users
WHERE is_deleted = 0
AND email_verified = 1;
SQLすると、アプリ側では、
SELECT * FROM active_users;
SQLと書くだけで、
退会しておらず、メール確認済みのユーザー
だけが取れるようになります。
もし「アクティブ」の定義を変えたくなっても、
ビューの定義を変えるだけで済みます。
アプリ側のSQLを書き換える必要はありません。
セキュリティの観点から見たビュー
「見せてよいカラムだけを切り出す“窓”として使える」
ビューは、セキュリティの観点でも役に立ちます。
例えば、users テーブルにこういうカラムがあったとします。
パスワードハッシュ
秘密のメモ
内部用フラグ
アプリや分析者に見せたくないカラムがある場合、
ビューで「見せてよいカラムだけ」を切り出すことができます。
CREATE VIEW users_public AS
SELECT
id,
name,
email
FROM users;
SQLアプリやBIツールには、
この users_public だけを参照させるようにすれば、
パスワードハッシュなどの機微情報に
うっかりアクセスされるリスクを減らせます。
MySQL では、ビュー単位で権限を設定することもできるので、
テーブルにはフル権限を持つ管理者だけがアクセス
一般ユーザーやアプリはビュー経由でしか見られない
という構成も取りやすくなります。
SQLite と MySQL のビューの“温度差”
「SQLiteでは“おまけ”、MySQLでは“設計の道具”」
SQLite にもビューはありますが、
単一アプリ内で完結
開発者1〜2人
SQLもアプリ内にベタ書き
という世界観だと、
「別にビューにしなくてもいいか」となりがちです。
MySQL では、
複数アプリから同じDBを参照
分析・BIツールも同じDBを見る
SQLを書く人が複数いる
という状況が増えます。
このとき、ビューは、
複雑なJOINや集計に名前を付けて再利用する
見せてよいデータだけを切り出す“窓”を作る
ビジネスロジック(アクティブユーザーの定義など)をDB側に寄せる
といった「設計の道具」として、かなり強力になります。
Day10 前半では、
ビュー=保存されたSELECT文
ビュー=意味のある名前を付けた“仮想テーブル”
という2つのイメージを持っておけば十分です。
Day10 前半のまとめ
ビューは「名前を付けて保存したSELECT文」であり、CREATE VIEW 名前 AS SELECT ... の形で定義すると、テーブルと同じように SELECT * FROM 名前 で参照できるが、実体のデータを持つのではなく、毎回元テーブルに対してSELECTが実行される“仮想テーブル”として振る舞う。
複雑なJOINやWHERE条件をビューに閉じ込めておくことで、アプリ側や他の開発者は「active_users や user_orders のような意味のある名前」を使うだけで済み、内部のSQLを知らなくても扱えるようになり、ビジネスロジックの変更もビュー定義の変更だけで反映できる。
セキュリティの観点では、ビューで「見せてよいカラムだけ」を切り出した users_public のような窓を作り、アプリや分析ツールにはそのビューだけを参照させることで、パスワードハッシュなどの機微情報への不要なアクセスを防ぎやすくなる。
後半では、
ビューの制限(更新できるビュー・できないビュー)、
パフォーマンス上の注意点、
マテリアライズドビューとの違い(MySQLではどう扱うか)
といった実務寄りの話を掘り下げていきます。
