ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
| この記事の要点 |
|
ビューとは何か
ビューは名前付きの SELECT 文です。実テーブルではないので、データの実体はビューには存在しません。アクセスのたびに元の SELECT が実行され、その結果が返されます。
-- 基本のビュー定義
CREATE VIEW active_users AS
SELECT id, name, email
FROM users
WHERE status = 'active' AND deleted_at IS NULL;
-- 使い方は普通のテーブルと同じ
SELECT * FROM active_users WHERE email LIKE '%@example.com';
-- 結合や集約を含むビュー
CREATE VIEW user_order_summary AS
SELECT
u.id AS user_id,
u.name,
COUNT(o.id) AS order_count,
COALESCE(SUM(o.amount), 0) AS total_amount,
MAX(o.created_at) AS last_order_at
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
GROUP BY u.id, u.name;
SELECT * FROM user_order_summary WHERE order_count >= 10;
主なメリット
| メリット | 具体例 |
|---|---|
| 複雑クエリの抽象化 | 10 個の JOIN を 1 つの SELECT に隠す |
| 権限の粒度管理 | users テーブル全体は見せず、特定列のみのビューに GRANT |
| 後方互換性 | テーブル分割後も旧アプリ向けに統合ビューを残す |
| レポート定義の再利用 | BI ツールがアクセスするビューを統一 |
| 論理的なデータモデル | 物理スキーマと業務ビューを分離 |
ビューの作成・変更・削除
-- 作成
CREATE VIEW v_name AS SELECT ... ;
-- 既存があれば置換(推奨)
CREATE OR REPLACE VIEW v_name AS SELECT ... ;
-- 削除
DROP VIEW v_name;
-- 依存ビューも巻き込んで削除
DROP VIEW v_name CASCADE; -- PostgreSQL / Oracle
-- ビュー一覧(PostgreSQL)
SELECT viewname FROM pg_views WHERE schemaname = 'public';
-- ビュー一覧(MySQL)
SHOW FULL TABLES IN dbname WHERE Table_type = 'VIEW';
-- ビュー定義の確認
SELECT view_definition FROM information_schema.views WHERE table_name = 'v_name';
-- Oracle
SELECT text FROM user_views WHERE view_name = 'V_NAME';
Updatable View(更新可能ビュー)
ビューに対して INSERT / UPDATE / DELETE を実行すると、内部的に元のテーブルに反映されます。条件:
- 単一テーブル由来であること(JOIN なし)
- DISTINCT / GROUP BY / HAVING / 集約関数 / UNION なし
- サブクエリで参照されるテーブルが同じでないこと(DB により差)
- すべての非 NULL カラムがビューに含まれている(INSERT する場合)
-- Updatable View の例
CREATE VIEW active_users AS
SELECT id, name, email, status
FROM users
WHERE deleted_at IS NULL;
-- 更新できる
UPDATE active_users SET status = 'banned' WHERE id = 1;
-- → 元の users テーブルが更新される
-- WITH CHECK OPTION を付けると、ビュー条件を満たさない更新を拒否
CREATE OR REPLACE VIEW active_users AS
SELECT id, name, email, status, deleted_at
FROM users
WHERE deleted_at IS NULL
WITH CHECK OPTION;
UPDATE active_users SET deleted_at = NOW() WHERE id = 1;
-- → ERROR: CHECK OPTION failed (ビューから外れる更新を拒否)
INSTEAD OF トリガで複雑ビューも更新可能に
JOIN や集約を含むビューでも、INSTEAD OF トリガーを定義すれば更新可能になります(Oracle / SQL Server / PostgreSQL):
-- PostgreSQL の例
CREATE VIEW user_with_role AS
SELECT u.id, u.name, r.name AS role_name
FROM users u JOIN roles r ON u.role_id = r.id;
CREATE OR REPLACE FUNCTION trg_user_with_role_update()
RETURNS TRIGGER AS $$
BEGIN
UPDATE users
SET role_id = (SELECT id FROM roles WHERE name = NEW.role_name),
name = NEW.name
WHERE id = NEW.id;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER user_with_role_update_trg
INSTEAD OF UPDATE ON user_with_role
FOR EACH ROW EXECUTE FUNCTION trg_user_with_role_update();
Materialized View(実体化ビュー)
通常のビューは毎回 SELECT を実行しますが、Materialized View は結果をテーブルとして保存してアクセスを高速化します。集計レポート等の重いクエリに有効。
| DB | 対応 |
|---|---|
| Oracle | ◯ CREATE MATERIALIZED VIEW |
| PostgreSQL | ◯ CREATE MATERIALIZED VIEW (9.3+) |
| SQL Server | △ Indexed View で代用 |
| MySQL | × 標準では非対応 (テーブル + cron で代替) |
-- PostgreSQL
CREATE MATERIALIZED VIEW user_sales_summary AS
SELECT
u.id, u.name,
COUNT(o.id) AS order_cnt,
SUM(o.amount) AS total
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
GROUP BY u.id, u.name;
-- 通常テーブルのようにアクセスできる
SELECT * FROM user_sales_summary WHERE total > 100000;
-- インデックスも貼れる
CREATE INDEX idx_uss_total ON user_sales_summary (total);
-- リフレッシュ(結果を再計算)
REFRESH MATERIALIZED VIEW user_sales_summary;
-- 同時アクセスを許可しながらリフレッシュ
REFRESH MATERIALIZED VIEW CONCURRENTLY user_sales_summary;
-- ★ CONCURRENTLY は UNIQUE INDEX が必須
-- Oracle: 高速リフレッシュ
CREATE MATERIALIZED VIEW LOG ON orders WITH PRIMARY KEY, ROWID INCLUDING NEW VALUES;
CREATE MATERIALIZED VIEW user_sales_summary
BUILD IMMEDIATE
REFRESH FAST ON COMMIT
AS SELECT ... ;
Inline View(FROM 句のサブクエリ)との比較
-- Inline View: その場限り
SELECT *
FROM (
SELECT department, AVG(salary) AS avg_sal
FROM employees
GROUP BY department
) t
WHERE t.avg_sal > 500000;
-- Named View: 再利用可能
CREATE VIEW dept_avg AS
SELECT department, AVG(salary) AS avg_sal
FROM employees
GROUP BY department;
SELECT * FROM dept_avg WHERE avg_sal > 500000;
SELECT * FROM dept_avg WHERE department = 'sales';
| 項目 | Inline View | Named View | Materialized View |
|---|---|---|---|
| 定義箇所 | クエリ内 | スキーマに永続 | スキーマに永続 |
| 実体化 | なし | なし | あり |
| 再利用 | × | ◯ | ◯ |
| 性能 | 都度実行 | 都度実行 | 高速(古い可能性) |
| 容量 | 0 | 0 | 大 |
権限管理での活用
-- 機密列を隠したビュー
CREATE VIEW user_public AS
SELECT id, name, created_at
FROM users;
-- email / password_hash / ssn は含めない
-- ロールに権限付与
GRANT SELECT ON user_public TO reporter_role;
REVOKE SELECT ON users FROM reporter_role;
-- → reporter_role は users 全体は見えず、user_public 経由のみ
-- 行レベルフィルタ
CREATE VIEW own_orders AS
SELECT * FROM orders WHERE user_id = current_user_id();
-- → 自分の注文だけ見えるビュー
性能の落とし穴
- ビューにビューを重ねるとクエリプランが肥大化し最適化が困難になる
- SELECT * を使ったビューは元テーブルへの列追加で意図せず展開される
- Updatable View に複雑な WITH CHECK OPTION を付けると更新性能が落ちる
- Materialized View はリフレッシュコストが高い → 夜間バッチで実行が定番
- Oracle の
REFRESH ON COMMITは更新トランザクションを遅らせるので注意
FAQ
Q: ビューはテーブルより遅い?
A: 通常ビューは元クエリと同等の性能。オプティマイザはビュー展開して最適化します。Materialized View はテーブルより速いことが多いです。
Q: ビューにインデックスを貼れる?
A: 通常ビューには不可(元テーブルのインデックスを使う)。Materialized View には可能。SQL Server の Indexed View も類似機能。
Q: ビュー越しに DML を発行できる条件は?
A: 単一テーブルベース、集約・GROUP BY・DISTINCT・UNION なし。条件を満たさない場合は INSTEAD OF トリガで実装。
Q: CREATE VIEW でテーブル定義変更時の影響は?
A: Oracle: 依存ビューが INVALID に → 自動再コンパイル。MySQL: SELECT * のビューは列が固定化される。PostgreSQL: SELECT 文の列削除はビューが壊れる。
ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript base URL 取得方法|window.location.origin と SSR/Node.js 対応
- 4 YouTube Data API v3 エラー一覧|403/400/404 の主要原因と切り分け
- 5 Spring Frameworkのアノテーション一覧
- 6 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 7 3Dグラフィックスとは|モデリング/レンダリング/主要ソフトウェア (Blender / Maya)
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- IPv6とは|128bitアドレス・コロン16進表記/::省略・リンクローカル・SLAAC・デュアルスタック NEW 2026-06-22 12:34:44
- VPNとは|暗号トンネル・サイト間/リモートアクセス・IPsec/SSL-VPN/WireGuardを解説 NEW 2026-06-22 12:19:10
- MAC アドレスフィルタリングの仕組みと限界 | ネットワーク入門 NEW 2026-06-22 12:19:10
- WebRTC とは ブラウザ間 P2P の音声・映像・データ通信 | ネットワーク入門 NEW 2026-06-22 12:17:25
- gRPC とは HTTP/2 + Protocol Buffers の高速 RPC | ネットワーク入門 NEW 2026-06-22 12:17:25
- HTTP/3 (QUIC) とは UDP ベースの低遅延 Web 通信 | ネットワーク入門 NEW 2026-06-22 12:17:25
- HTTP/2 とは 多重化・HPACK・バイナリフレーム | ネットワーク入門 NEW 2026-06-22 12:17:25
- Web通信プロトコル入門 HTTP/2・HTTP/3・WebSocket・gRPC・WebRTC | ネットワーク入門 NEW 2026-06-22 12:17:25
- WebSocket とは 全二重リアルタイム通信 ws/wss | ネットワーク入門 NEW 2026-06-22 12:17:25
- ファイアウォールとは|パケットフィルタ・ステートフル・DMZ・次世代FW(L4/L7)を解説 NEW 2026-06-22 12:17:24
- iptables/nftablesとは|テーブル・チェーン・ルール例・永続化をLinux視点で解説 NEW 2026-06-22 12:17:24
- HAProxy とは frontend/backend と設定例 | ネットワーク入門 NEW 2026-06-22 12:17:24
- 証明書と認証局(CA)とは|X.509・信頼チェーン・DV/OV/EV・失効(CRL/OCSP)を解説 NEW 2026-06-22 12:17:24
- CDN とは エッジキャッシュ・TTL・Cloudflare/CloudFront | ネットワーク入門 NEW 2026-06-22 12:17:24
- TLS/SSLの仕組み|ハンドシェイク・暗号スイート・前方秘匿性・証明書検証をわかりやすく解説 NEW 2026-06-22 12:17:24
コメントを削除してもよろしいでしょうか?