MySQL | SQLite経験者向け、30日で習得するMySQL:実務SQL力 - Day10 ビュー

SQL MySQL
スポンサーリンク

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_usersmonthly_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_usersuser_orders のような意味のある名前」を使うだけで済み、内部のSQLを知らなくても扱えるようになり、ビジネスロジックの変更もビュー定義の変更だけで反映できる。
セキュリティの観点では、ビューで「見せてよいカラムだけ」を切り出した users_public のような窓を作り、アプリや分析ツールにはそのビューだけを参照させることで、パスワードハッシュなどの機微情報への不要なアクセスを防ぎやすくなる。

後半では、
ビューの制限(更新できるビュー・できないビュー)、
パフォーマンス上の注意点、
マテリアライズドビューとの違い(MySQLではどう扱うか)
といった実務寄りの話を掘り下げていきます。

タイトルとURLをコピーしました