メインコンテンツへスキップ

VillageSQL is a drop-in replacement for MySQL with extensions.

All examples on this page work on VillageSQL. Install Now →
生成列とは、アプリケーションが格納するのではなく、式から値が導出される列です。MySQL がそれを自動的に計算します。スキーマで計算式を一度定義すれば、MySQL がその一貫性を保ちます。

構文

VIRTUAL と STORED の比較

計算が高コストで、列を書き込むよりはるかに多く読み取る場合は STORED を使います。格納容量が懸念される場合や、書き込みが頻繁に起こる場合は VIRTUAL(デフォルト)を使います。

式

生成列の式は、同じ行の他の列を参照できます。他の生成列を参照したり、非決定的な関数を呼び出したりすることはできません。
生成列で許可される関数は決定的でなければなりません。同じ入力が常に同じ出力を生成するものです。許可されないもの: NOW()、RAND()、UUID()、サブクエリ、ストアド関数。 JSON からフィールドを抽出するのはよくある使い方です。

生成列へのインデックス作成

生成列にインデックスを追加できます。VIRTUAL 列の場合、MySQL は計算された値をインデックスに実体化します。
これは関数インデックス、つまり列の生の値ではなく列の関数に対するインデックスを構築する方法でもあります。MySQL 8.0.13 以降は関数インデックスを直接サポートしており(INDEX (LOWER(email)))、内部的に隠れた生成列を作成します。

挿入と更新

INSERT や UPDATE で生成列に値を代入することはできません。列の値は常に式から導出されます。明示的に DEFAULT と書くことはできますが、それだけです。

ALTER TABLE

既存のテーブルに生成列を追加します。
生成列の式を変更します。VIRTUAL/STORED の格納クラスは同じままでなければなりません。切り替えると ERROR 3106: 'Changing the STORED status' is not supported for generated columns が発生するため、格納クラスの変更には列の削除と再追加が必要です。

よくある質問

WHERE 句で生成列を使えますか?

はい。インデックスのない VIRTUAL 列の場合、MySQL はスキャン中に式を計算します。STORED 列またはインデックス付きの VIRTUAL 列の場合、値はすでに実体化されています。インデックスが使われているかどうかは EXPLAIN で確認してください。

元の列が変わると、生成列は自動的に更新されますか?

はい。MySQL は VIRTUAL 生成列を読み取りのたびに再計算します。STORED 生成列は、式の中の列に影響するすべての INSERT または UPDATE で再計算されて書き込まれます。

生成列をパーティションキーとして使えますか?

はい。STORED と VIRTUAL のどちらの生成列でも使えます。

トラブルシューティング

関連項目