🐷

SQLのVIEWを調べてみた

2024/02/26に公開

概要

業務で初めて VIEW を使う機会があり、VIEW について何も知らなかったため調べてみました。

注意

筆者は RDBMS・SQL について初心者のため、間違った理解をしている可能性が高いです。
本文中に間違いがありましたらコメントにてご指摘頂けますと幸いです 🙏

TL;DR

  • VIEW は SQL によって中身が定義される仮想的なテーブル
  • VIEW 自体はデータの実態を持たない
  • VIEW は「複雑なクエリをシンプルにする」・「セキュリティの確保」・「レガシーコード退治」に役立つ

検証環境

PostgreSQL 16.1

VIEW とは何か

VIEW とは SQL によって定義される仮想的なテーブルです。
なぜテーブルではなく 仮想的な テーブルと呼ばれるかというと、テーブルのようにストレージ上にデータを保存しないためです。
VIEW は呼び出されるたびに VIEW に定義されているクエリを実行してテーブルからデータを取得します。

view-flow

この図の VIEW では employees テーブルと departments テーブルを join して特定のカラムを select しています。
(めっちゃ見にくい図でごめんなさい 🙏)

VIEW の作成~削除

VIEW の作成~削除の一連の流れをコードで説明していきます。

以下のクエリでは従業員テーブル(employees)と部署テーブル(departments)を作成してサンプルデータを投入してます。
従業員テーブルは部署テーブルに対する外部キーとして department_id を持ちます。

CREATE TABLE departments (
    id          INT             NOT NULL,
    name        VARCHAR(14)     NOT NULL,
    rank        VARCHAR(14)     NOT NULL,
    PRIMARY KEY (id)
);
INSERT INTO departments VALUES (1, 'corporate', 'A'), (2, 'sales', 'B');

CREATE TABLE employees (
    id            INT             NOT NULL,
    department_id INT             NOT NULL,
    name          VARCHAR(14)     NOT NULL,
    salary        INT             NOT NULL,
    FOREIGN KEY   (department_id) REFERENCES departments (id) ON DELETE CASCADE,
    PRIMARY KEY   (id)
);
INSERT INTO employees VALUES (1, 1, 'Tom', 10000), (2, 2, 'Mike', 20000);

VIEW の作成には CREATE VIEW を使用します。
以下では

  • 従業員 id(employees.id)
  • 従業員名(employees.name)
  • 従業員の給料(employees.salary)
  • 従業員が所属する部署の名前(departments.name)

を取得する EmployeesWithDepartment View を作成しています。

playground> CREATE VIEW EmployeesWithDepartment AS
 SELECT
   employees.id AS id,
   employees.name AS name,
   salary,
   departments.name AS department_name
 FROM employees
 LEFT JOIN departments
 ON Employees.department_id = departments.id
CREATE VIEW
Time: 0.011s

次は呼び出し方です。
上記で定義した EmployeesWithDepartment VIEW をクエリの中で呼び出します。
呼び出し方はテーブルに対してクエリを実行するのと変わりません。

playground> SELECT * FROM EmployeesWithDepartment;
+----+------+--------+-----------------+
| id | name | salary | department_name |
|----+------+--------+-----------------|
| 1  | Tom  | 10000  | corporate       |
| 2  | Mike | 20000  | sales           |
+----+------+--------+-----------------+
SELECT 2
Time: 0.009s

ここで部署名に加えて部署のランク(departments.rank)も取得したくなったとします。
既に対象の VIEW が存在する場合は更新して存在しなければ作成する場合 CREATE OR REPLACE を使用します。

playground> CREATE OR REPLACE VIEW EmployeesWithDepartment AS
 SELECT
   employees.id AS id,
   employees.name AS name,
   salary,
   departments.name AS department_name,
   departments.rank AS department_rank
 FROM employees
 LEFT JOIN departments
 ON Employees.department_id = departments.id
CREATE VIEW
Time: 0.006s
playground> SELECT * FROM EmployeesWithDepartment;
+----+------+--------+-----------------+-----------------+
| id | name | salary | department_name | department_rank |
|----+------+--------+-----------------+-----------------|
| 1  | Tom  | 10000  | corporate       | A               |
| 2  | Mike | 20000  | sales           | B               |
+----+------+--------+-----------------+-----------------+
SELECT 2
Time: 0.009s

もう一度呼び出すと department_rank カラムも取得できていることが分かります。

最後に VIEW の削除です。
VIEW を削除するには DROP VIEW を使用します。

playground> DROP VIEW EmployeesWithDepartment;
You're about to run a destructive command.
Do you want to proceed? [y/N]: y
Your call!
DROP VIEW
Time: 0.009s

VIEW の使い所

VIEW について何となく分かったところで、具体的にどのようなユースケースで使用するのか分からず調べている中で以下の記事に出会いました。

Why do you create a View in a database?

この記事では VIEW の使い所として以下の 3 つが提唱されていました。

1. 複雑なクエリをシンプルにする

複数のテーブルをジョインしたり、ジョインした結果から何段階にも渡って計算してデータを取得するようなクエリがあったとします。このようなクエリの内部に存在するロジックを VIEW として外部に切り出すことでテーブルを呼び出す感覚でクエリを実行出来ます。
実際、自分が今回の業務で VIEW を扱った目的はこのためでした。

2. セキュリティの確保

VIEW に対して permission を設定することで特定のユーザに必要なデータのみ公開するよう設定することができます。
今回の調査ではセキュリティ確保の具体的な方法について調べることが時間的に難しかったため次回までの宿題とします。
軽く調べただけですが、例えばMySQL の公式リファレンスでは以下のように記されていました。

DEFINER および SQL SECURITY 句は、そのビューを参照しているステートメントの実行時に、そのビューに対するアクセス権限を確認するときにどの MySQL アカウントを使用するかを決定します。 有効な SQL SECURITY 特性値は、DEFINER (デフォルト) および INVOKER です。 これらは、それぞれ、そのビューを定義したユーザーまたは呼び出したユーザーが必要な権限を持っている必要があることを示します。

3. レガシーコード退治

レガシーコード退治においてテーブルのリファクタリングが難しい場合、テーブルを同じ名前のビューに置き換えるという手法が考えられます。既存のテーブルと同じ VIEW を用意しておくことでテーブルのスキーマが変更されても VIEW は影響を受けないため安全にリファクタリングを進めることができます。
今回の調査では VIEW を使ったレガシーコード退治の事例を見つけることができなかったためセキュリティの確保と同様にこちらも次回までの宿題とします。

最後に

今回の VIEW の調査を通して VIEW の概要や VIEW の作成~削除の流れ、使い所などをざっくりではありますが勉強することが出来ました。
PostgreSQL には、通常の VIEW とは異なる性質を持つ Materialized View というものが存在します。これは、VIEW とテーブルの中間のような性質を持ちます。次回はこの Materialized View について調査しつつ、今回調べきれなかった VIEW の適切な使用方法について調べる予定です。

参考記事

(データベース)view の使い所
Views (Virtual Tables) in SQL
Why do you create a View in a database?
What is an SQL View

GitHubで編集を提案

Discussion