リレーショナルデータベースにおける仮想表(ビュー)の定義と実装方法

1. 仮想表(ビュー)の基本概念

仮想表(ビュー)は物理的なデータ領域を消費しない論理オブジェクトです。実際にはデータディクショナリに定義文のみが格納され、クエリが実行されるたびに基盤となる実表(ベーステーブル)に対して動的にSQLが展開されます。基表のデータ変更は即座に仮想表の出力結果に反映されます。なお、物理的なデータスナップショットを保持するマテリアライズドビューとは仕組みが異なります。

2. 導入による主な効果

  • データ表現の抽象化: 別名(エイリアス)を用いて基表のカラム名やデータ形式を再利用者向けに最適化できます。
  • 複雑なクエリの隠蔽: 複数表の結合や集計ロジックを定義内に封じ込め、利用者は単純なSELECT文で結果を取得可能です。
  • セキュリティ制御: 機微なカラムを定義から除外することで、行単位または列単位でのアクセス制限を実現します。
  • 権限管理の簡素化: 実表のカラム単位での権限付与ではなく、仮想表単位でアクセス権を一元管理できます。

3. 構築手順と構文オプション

現在のスキーマに仮想表を作成するには CREATE VIEW システム権限が、他スキーマに作成するには CREATE ANY VIEW 権限が必要です。動作特性は定義所有者の権限に依存します。

基本的な構文は以下の通りです:

CREATE [OR REPLACE] [FORCE] VIEW [スキーマ.]ビュー名
    [(列別名1, 列別名2, ...)]
AS
    SELECT ...
    [WITH CHECK OPTION] [CONSTRAINT 制約名]
    [WITH READ ONLY];

主なオプションの動作:

  • OR REPLACE:同名オブジェクトが存在する場合、定義を上書きします。既存の権限付与は保持されますが、依存オブジェクトは無効化されます。
  • FORCE:基表が存在しない状態でも定義文の文法エラーがなければ作成を許可します。この場合、仮想表は INVALID 状態で格納されます。
  • WITH CHECK OPTION:DML実行時、定義の WHERE 句で指定された条件に合致するレコードのみを対象とします。条件外のデータ挿入や更新はエラーとなります。
  • WITH READ ONLY:参照専用モードを強制し、INSERT/UPDATE/DELETE 操作をブロックします。

3.1 基本仮想表の作成例

単一実表を基に、関数や集計を含まない単純な構造を作成します。

CREATE OR REPLACE VIEW vw_staff_basic AS
SELECT staff_id, full_name, job_title, hire_dt, branch_code
FROM staff_tbl;

-- 参照とDML操作(基表へ直接影響)
SELECT full_name, job_title FROM vw_staff_basic WHERE branch_code = 10;
INSERT INTO vw_staff_basic VALUES(101, 'Tanaka', 'Dev', SYSDATE, 10);
UPDATE vw_staff_basic SET job_title = 'Senior Dev' WHERE staff_id = 101;
DELETE FROM vw_staff_basic WHERE staff_id = 101;

3.2 参照専用モードの適用

意図しない基表変更を防ぐために、読み取り専用オプションを付与します。

CREATE VIEW vw_staff_secure AS
SELECT staff_id, full_name, job_title
FROM staff_tbl WITH READ ONLY;

-- 正常動作
SELECT * FROM vw_staff_secure WHERE branch_code = 20;

-- エラー発生(ORA-42399相当)
DELETE FROM vw_staff_secure WHERE staff_id = 101;

3.3 更新制限付き仮想表(WITH CHECK OPTION)

定義条件外のデータ変更を強制防止します。

CREATE VIEW vw_branch_a_staff AS
SELECT staff_id, full_name, branch_code
FROM staff_tbl
WHERE branch_code = 10 WITH CHECK OPTION;

-- 条件内のため成功
INSERT INTO vw_branch_a_staff VALUES(201, 'Sato', 10);

-- 条件外のため失敗(ORA-01402相当)
INSERT INTO vw_branch_a_staff VALUES(202, 'Suzuki', 20);

4. 結合仮想表と更新可能性

複数実表の結合結果を基にした仮想表です。結合ビュー上でのDML操作は、基表の整合性を維持するため厳密なルールが適用されます。

4.1 キー保存表の概念

結合結果において、特定の基表の主キーまたは一意キーが仮想表上でも一意性を維持している場合、その基表を「キー保存表」と呼びます。DML操作は原則としてキー保存表に対してのみ許可されます。

4.2 結合仮想表の作成と制限

CREATE VIEW vw_staff_org AS
SELECT b.branch_code, b.branch_name, s.staff_id, s.full_name, s.monthly_pay
FROM branch_tbl b
INNER JOIN staff_tbl s ON b.branch_code = s.branch_code
WHERE b.branch_code IN (10, 30);

結合ビューに対するDMLの適用原則:

  • 1回のDML文で複数の基表を同時に更新することはできません。
  • INSERT 操作では、非キー保存表のカラムや結合条件カラムを指定できません。
  • WITH CHECK OPTION が設定されている場合、INSERT は完全に禁止され、結合カラムの UPDATE も制限されます。ただし DELETE は許可されます。

以下の構成要素を含む結合ビューはDML更新が不可能となります:集合演算子(UNION/INTERSECT/MINUS)、DISTINCT、GROUP BY/ORDER BY/CONNECT BY、相関サブクエリ、集計関数、NOT NULL制約を持つ基表カラムの欠落、列式による計算結果。

5. 複雑仮想表と強制作成

集計関数や数式を含む仮想表は、主に分析クエリの簡素化を目的とします。関数や演算式を使用する場合、列別名の定義が必須です。

CREATE VIEW vw_role_stats AS
SELECT job_title,
       ROUND(AVG(monthly_pay), 2) AS avg_pay,
       MAX(monthly_pay) AS max_pay,
       MIN(monthly_pay) AS min_pay
FROM staff_tbl
GROUP BY job_title;

基表が未作成の状態で FORCE オプションを使用した場合、仮想表は INVALID 状態で作成されます。基表が作成されるまで参照はエラーになりますが、基表の準備完了後は自動的に VALID に状態遷移します。

CREATE FORCE VIEW vw_temp_data AS
SELECT col_x, col_y FROM temp_source;
-- 基表作成前は ORA-04063 相当エラー。基表作成後は正常参照可能。

6. 定義の変更と再コンパイル

仮想表の定義を更新する際は、CREATE OR REPLACE を使用します。これにより既存の権限付与は維持されますが、依存するプロシージャや他の仮想表は INVALID へ移行します。

基表の構造変更(カラム型変更、追加、削除など)により仮想表が無効化された場合、明示的な再コンパイルを実行して状態を検証できます。

-- 手動再コンパイル
ALTER VIEW vw_staff_basic COMPILE;

-- ステータス確認
SELECT object_name, status, last_ddl_time 
FROM user_objects 
WHERE object_name = 'VW_STAFF_BASIC';

再コンパイル実行時、定義に問題がなければ VALID へ復帰し、依存オブジェクトも連鎖して有効化されます。エラーがある場合は INVALID が維持されます。なお、Oracleは無効な仮想表への初回アクセス時に自動再コンパイルを試行します。

7. 削除とメタデータの参照

仮想表の削除には DROP VIEW を使用します。削除に伴い、定義情報と当該オブジェクトに付与された権限は完全に消去され、依存オブジェクトは INVALID へ移行します。他スキーマの削除には DROP ANY VIEW 権限が必要です。

DROP VIEW vw_staff_basic;

定義内容やカラム情報はデータディクショナリから確認可能です。

-- 定義SQLの確認
SELECT view_name, text FROM user_views;

-- カラム属性の確認
SELECT column_name, data_type, data_length, nullable 
FROM user_tab_columns 
WHERE table_name = 'VW_STAFF_SECURE';

8. DML操作の内部動作と更新可否の判定

仮想表に対するクエリは、内部的に「ビューマージ」または「ビュー展開」のプロセスを経て実行されます。利用者が発行したSQLとデータディクショナリに保存された定義文が統合され、共有プール内で構文解析・最適化された後、実際の基表に対して実行計画が生成されます。

各カラムの更新可否はシステムビューを通じてプログラム的に判定できます。

SELECT table_name, 
       column_name, 
       insertable, 
       updatable, 
       deletable
FROM user_updatable_columns
WHERE table_name LIKE 'VW_%';

上記クエリの結果は、結合ビューのキー保存性、集計関数の有無、WITH CHECK OPTIONWITH READ ONLY の設定状態などを反映し、INSERT/UPDATE/DELETE の実行可否を YES / NO で返します。これにより、アプリケーションレベルで動的にDML操作の許容範囲を制御するロジック実装が可能となります。

タグ: SQL 仮想表 Oracleデータベース データディクショナリ DML操作

7月11日 20:15 投稿