MySQL 8.0 リファレンスマニュアル


MySQL 8.0 リファレンスマニュアル  /  ...  /  更新可能および挿入可能なビュー

25.5.3 更新可能および挿入可能なビュー

一部のビューは更新可能であり、それらへの参照を使用して、データ変更ステートメントで更新するテーブルを指定できます。 つまり、これらのビューを UPDATEDELETEINSERT などのステートメントで使用して、ベースとなるテーブルの内容を更新できます。 導出テーブルおよび共通テーブル式は、複数テーブルの UPDATE ステートメントおよび DELETE ステートメントでも指定できますが、更新または削除する行を指定するためのデータの読取りにのみ使用できます。 通常、ビュー参照は更新可能である必要があります。つまり、マージされて実体化されない場合があります。 コンポジットビューには、より複雑なルールがあります。

ビューが更新可能であるためには、そのビュー内の行とベースとなるテーブル内の行の間に 1 対 1 の関係が存在する必要があります。 また、ビューを更新不可能にするその他の特定の構造構文も存在します。 より具体的には、次のいずれかを含む場合、ビューは更新可能ではありません。

  • 集計関数またはウィンドウ関数 (SUM(), MIN(), MAX(), COUNT() など)

  • DISTINCT

  • GROUP BY

  • HAVING

  • UNION または UNION ALL

  • 選択リスト内のサブクエリー

    選択リスト内の非依存サブクエリーは、INSERT では失敗しますが、UPDATEDELETE では問題ありません。 選択リスト内の依存サブクエリーの場合、データ変更ステートメントは許可されません。

  • 特定の結合 (このセクションで後述する結合に関する追加説明を参照してください)

  • FROM 句内の更新不可ビューへの参照

  • FROM 句のテーブルを参照する WHERE 句のサブクエリー

  • リテラル値だけの参照 (この場合、更新するベースとなるテーブルがありません)

  • ALGORITHM = TEMPTABLE (一時テーブルを使用すると、常にビューが更新不可になります)

  • 実テーブルの任意のカラムへの複数の参照 (INSERT では失敗、UPDATEDELETE では OK)

ビュー内の生成されたカラムは、割り当て可能であるため、更新可能とみなされます。 ただし、このようなカラムが明示的に更新される場合、許可される値は DEFAULT のみです。 生成されるカラムの詳細は、セクション13.1.20.8「CREATE TABLE および生成されるカラム」 を参照してください。

MERGE アルゴリズムで処理できるとすれば、複数テーブルビューが更新できる可能性があります。 これを実現するには、ビューで (外部結合または UNION ではなく) 内部結合を使用する必要があります。 また、ビュー定義内の単一のテーブルだけを更新できるので、SET 句は、ビュー内のいずれかのテーブルのカラムだけを指名する必要があります。 理論的には更新可能であっても、UNION ALL を使用するビューは許可されません。

挿入可能性 (INSERT ステートメントで更新可能であること) については、更新可能なビューがビューカラムに対する次の追加要件も満たしている場合に挿入可能になります。

  • 重複したビューカラム名が存在しないようにする必要があります。

  • ビューには、デフォルト値を持たない、ベーステーブル内のすべてのカラムが含まれている必要があります。

  • ビューカラムは単純なカラム参照である必要があります。 次のような式は使用できません:

    3.14159
    col1 + 3
    UPPER(col2)
    col3 / col4
    (subquery)

MySQL は、CREATE VIEW 時に、ビューの更新可能性フラグというフラグを設定します。 UPDATE および DELETE (および同様の操作) がビューで有効な場合、フラグは YES (true) に設定されます。 それ以外の場合、フラグは NO (false) に設定されます。 INFORMATION_SCHEMA.VIEWS テーブルの IS_UPDATABLE カラムは、このフラグのステータスを表示します。 これは、ビューが更新可能であるかどうかをサーバーが常に把握していることを意味します。

ビューが更新可能でない場合、UPDATEDELETE および INSERT などのステートメントは無効であり、拒否されます。 (ビューが更新可能であっても、このセクションの別の場所で説明されているように、ビューに挿入できない場合があります。)

ビューを更新できるかどうかは、updatable_views_with_limit システム変数の値に影響されます。 セクション5.1.8「サーバーシステム変数」を参照してください。

次の説明では、これらのテーブルおよびビューが存在するとします:

CREATE TABLE t1 (x INTEGER);
CREATE TABLE t2 (c INTEGER);
CREATE VIEW vmat AS SELECT SUM(x) AS s FROM t1;
CREATE VIEW vup AS SELECT * FROM t2;
CREATE VIEW vjoin AS SELECT * FROM vmat JOIN vup ON vmat.s=vup.c;

INSERTUPDATE および DELETE ステートメントは、次のように許可されます:

  • INSERT: INSERT ステートメントの挿入テーブルは、マージされるビュー参照である場合があります。 ビューが結合ビューの場合、ビューのすべてのコンポーネントは更新可能である必要があります (実体化されていません)。 更新可能な複数テーブルビューでは、INSERT は、単一のテーブルに挿入する場合に機能します。

    結合ビューのいずれかのコンポーネントが更新不可であるため、このステートメントは無効です:

    INSERT INTO vjoin (c) VALUES (1);

    このステートメントは有効です。ビューには実体化コンポーネントが含まれていません:

    INSERT INTO vup (c) VALUES (1);
  • UPDATE: UPDATE ステートメントで更新されるテーブルは、マージされるビュー参照である場合があります。 ビューが結合ビューの場合、ビューの少なくとも 1 つのコンポーネントが更新可能である必要があります (INSERT とは異なります)。

    複数テーブルの UPDATE ステートメントでは、ステートメントの更新されたテーブル参照は実テーブルまたは更新可能なビュー参照である必要があります。 更新されていないテーブル参照は、実体化ビューまたは導出テーブルです。

    次のステートメントは有効です。カラム c は結合ビューの更新可能な部分のものです:

    UPDATE vjoin SET c=c+1;

    このステートメントは無効です。カラム x は更新不可能な部分のものです:

    UPDATE vjoin SET x=x+1;

    次のステートメントは有効です。複数テーブルの UPDATE の更新されたテーブル参照は更新可能なビュー (vup) です:

    UPDATE vup JOIN (SELECT SUM(x) AS s FROM t1) AS dt ON ...
    SET c=c+1;

    このステートメントは無効です。実体化導出テーブルを更新しようとしています:

    UPDATE vup JOIN (SELECT SUM(x) AS s FROM t1) AS dt ON ...
    SET s=s+1;
  • DELETE: DELETE ステートメントで削除するテーブルは、マージビューである必要があります。 結合ビューは使用できません (INSERT および UPDATE とは異なります)。

    ビューが結合ビューであるため、このステートメントは無効です:

    DELETE vjoin WHERE ...;

    このステートメントは、ビューがマージ (更新可能) ビューであるため有効です:

    DELETE vup WHERE ...;

    このステートメントは、マージされた (更新可能な) ビューから削除されるため有効です:

    DELETE vup FROM vup JOIN (SELECT SUM(x) AS s FROM t1) AS dt ON ...;

その他の説明と例を次に示します。

このセクションの以前の説明では、すべてのカラムが単純なカラム参照ではない場合 (たとえば、式または複合式であるカラムが含まれている場合)、ビューを挿入できないことを指摘していました。 このようなビューは挿入できませんが、式ではないカラムのみを更新すると更新できます。 次のビューを考えてみてください。

CREATE VIEW v AS SELECT col1, 1 AS col2 FROM t;

col2 が式であるため、このビューは挿入できません。 ただし、更新で col2 を更新しようとしていない場合は、更新可能になります。 次の更新は許可されます。

UPDATE v SET col1 = 0;

式カラムを更新しようとしているため、この更新は許可されません:

UPDATE v SET col2 = 0;

テーブルに AUTO_INCREMENT カラムが含まれている場合、AUTO_INCREMENT カラムが含まれていないテーブル上の挿入可能なビューに挿入すると、LAST_INSERT_ID() の値を変更しません。これは、ビューの一部ではないカラムにデフォルト値を挿入した副作用が現れないようにするためです。


関連キーワード:  更新, テーブル, ステートメント, カラム, UPDATE, 参照, INSERT, 挿入, 結合, FROM