Documentation Home
MySQL 5.6 リファレンスマニュアル
Download this Manual
PDF (US Ltr) - 26.8Mb
PDF (A4) - 26.9Mb
HTML Download (TGZ) - 7.1Mb
HTML Download (Zip) - 7.2Mb


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

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

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

  • 集計関数 (SUM()MIN()MAX()COUNT() など)

  • DISTINCT

  • GROUP BY

  • HAVING

  • UNION または UNION ALL

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

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

  • FROM 句内の更新不可能なビュー

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

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

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

  • ベーステーブルのいずれかのカラムに対する複数の参照。

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

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

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

  • ビューカラムは、派生カラムではなく、単純なカラム参照である必要があります。派生カラムは、単純なカラム参照ではなく、式から派生したカラムです。派生したカラムの例は次のとおりです。

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

単純なカラム参照と派生カラムが混在しているビューは挿入できませんが、派生カラム以外のカラムだけを更新する場合は、更新可能になります。次のビューを考えてみてください。

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

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

UPDATE v SET col1 = 0;

次の更新は、派生カラムを更新しようとしているので、許可されません。

UPDATE v SET col2 = 0;

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

更新可能な複数テーブルビューでは、INSERT は、単一のテーブルに挿入する場合に機能します。DELETE はサポートされません。

INSERT DELAYED は、ビューではサポートされません。

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

更新可能なビューに対して WITH CHECK OPTION 句を指定すると、select_statement 内の WHERE 句が true である行を除く行への挿入または更新を回避できます。

更新可能なビューに対する WITH CHECK OPTION 句では、そのビューが別のビューとの関連で定義されている場合、LOCAL および CASCADED キーワードによってチェックテストのスコープが決定されます。LOCAL キーワードは、CHECK OPTION を、定義されているビューのみに制限します。CASCADED を指定すると、ベースとなるビューに対するチェックも評価されます。どちらのキーワードも指定されていない場合、デフォルトは CASCADED になります。次のテーブルと一連のビューの定義を考えてみてください。

mysql> CREATE TABLE t1 (a INT);
mysql> CREATE VIEW v1 AS SELECT * FROM t1 WHERE a < 2
    -> WITH CHECK OPTION;
mysql> CREATE VIEW v2 AS SELECT * FROM v1 WHERE a > 0
    -> WITH LOCAL CHECK OPTION;
mysql> CREATE VIEW v3 AS SELECT * FROM v1 WHERE a > 0
    -> WITH CASCADED CHECK OPTION;

ここで、v2 および v3 ビューは、v1 という別のビューの観点で定義されています。v2 には LOCAL チェックオプションがあるので、挿入は、v2 チェックに対してのみテストされます。v3 には CASCADED チェックオプションがあるので、挿入はそれ自身のチェックに対してだけでなく、ベースとなるビューのチェックに対してもテストされます。次のステートメントでこれらの違いを示しています。

mysql> INSERT INTO v2 VALUES (2);
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO v3 VALUES (2);
ERROR 1369 (HY000): CHECK OPTION failed 'test.v3'

MySQL は、CREATE VIEW 時に、ビューの更新可能性フラグというフラグを設定します。UPDATE および DELETE (および同様の操作) がビューで有効な場合、フラグは YES (true) に設定されます。それ以外の場合、フラグは NO (false) に設定されます。INFORMATION_SCHEMA.VIEWS テーブルの IS_UPDATABLE カラムは、このフラグのステータスを表示します。これは、ビューが更新可能であるかどうかをサーバーが常に把握していることを意味します。ビューが更新可能ではない場合、UPDATEDELETEINSERT などのステートメントは無効であり、拒否されます。(このセクションの別の箇所で説明しているように、ビューが更新可能である場合でも、ビューへの挿入はできない場合もあります。)

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


User Comments
User comments in this section are, as the name implies, provided by MySQL users. The MySQL documentation team is not responsible for, nor do they endorse, any of the information provided here.
  Posted by Jannes Faber on October 31, 2013
If a VIEW is not-updatable because of something in the WHERE clause (use of a function for example) then there's a trick to make it updatable again.

This is not-updatable:

CREATE OR REPLACE ALGORITHM=MERGE VIEW user1 AS
SELECT u1.*
FROM users u1
WHERE u1.ID=CurrentUserID()
AND u1.Deleted=0
-- WITH CHECK OPTION -- not possible
;

However, by moving the WHERE clause to an INNER JOIN it does work:

CREATE OR REPLACE ALGORITHM=MERGE VIEW user1 AS
SELECT u1.*
FROM users u1
INNER JOIN tradingsystem.users u2 ON u2.ID=u1.ID AND u2.ID=CurrentUserID()
WHERE u1.Deleted=0
WITH CHECK OPTION
;

Not it's perfectly updatable, except trying to change the ID or Deleted field would result in "Error Code: 1369. CHECK OPTION failed 'user1'". Which is as expected.

The downside is of course the extra JOIN, but as we're talking about primary keys here that should be pretty quick (eq_ref) or (in my case) be optimized as "const" anyway. Check EXPLAIN SELECT * FROM user1; for yourself.
Sign Up Login You must be logged in to post a comment.