コンテンツにスキップ

生成されたカラム

D1では、1つ以上の他のカラムの値、SQL関数、または抽出されたJSON値に基づいて生成されたカラムを定義することができます。

これにより、テーブルに書き込む際や読み取る際にデータを正規化でき、クエリが容易になり、複雑なアプリケーションロジックの必要性が減ります。

生成されたカラムには、インデックスを定義することもでき、頻繁にクエリされるフィールドに対するクエリパフォーマンスを劇的に向上させることができます。

生成されたカラムの種類

生成されたカラムには2つの種類があります:

  • VIRTUAL(デフォルト):カラムは読み取られるときに生成されます。これはストレージを消費しない利点がありますが、計算時間が増加する可能性があり(したがってクエリパフォーマンスが低下する可能性があります)、特に大きなクエリの場合に影響があります。
  • STORED:カラムは行が書き込まれるときに生成されます。このカラムは通常のカラムと同様にストレージスペースを占有しますが、毎回読み取るたびに生成する必要がないため、読み取りクエリのパフォーマンスが向上する可能性があります。

生成されたカラムの式から省略された場合、生成されたカラムはデフォルトでVIRTUALタイプになります。生成されたカラムが計算集約的な場合はSTOREDタイプを推奨します。例えば、大きなJSON構造を解析する場合です。

生成されたカラムの定義

生成されたカラムは、CREATE TABLEステートメントでテーブル作成時に定義するか、ALTER TABLEステートメントを介して後から定義することができます。

生成されたカラムを定義するテーブルを作成するには、ASキーワードを使用します:

CREATE TABLE some_table (
-- 他のカラムは省略
some_generated_column AS <function_that_generates_the_column_data>
)

具体的な例として、以下のJSONセンサーデータからlocation値を自動的に抽出するために、raw_dataカラムに基づいてTEXT型のlocationという生成されたカラムを定義できます。

{
"measurement": {
"temp_f": "77.4",
"aqi": [21, 42, 58],
"o3": [18, 500],
"wind_mph": "13",
"location": "US-NY"
}
}

$.measurement.locationの値を持つ生成されたカラムを定義するには、raw_dataカラムから値を抽出するためにjson_extract関数を使用します:

CREATE TABLE sensor_readings (
event_id INTEGER PRIMARY KEY,
timestamp INTEGER NOT NULL,
raw_data TEXT,
location as (json_extract(raw_data, '$.measurement.location')) STORED
);

生成されたカラムは、column_name GENERATED ALWAYS AS <function> [STORED|VIRTUAL]構文でオプションとして指定できます。GENERATED ALWAYS構文はオプションであり、省略した場合でも生成されたカラムの動作は変わりません。

既存のテーブルに生成されたカラムを追加

生成されたカラムは、既存のテーブルにも追加できます。もしsensor_readingsテーブルに生成されたlocationカラムがなかった場合、ALTER TABLEステートメントを実行して追加できます:

ALTER TABLE sensor_readings
ADD COLUMN location as (json_extract(raw_data, '$.measurement.location'));

これは、各読み取りクエリでjson_extractを実行するVIRTUAL生成されたカラムを定義します。

生成されたカラムの定義は直接変更できません。生成されたカラムがデータを生成する方法を変更するには、ALTER TABLE table_name REMOVE COLUMNを使用してからADD COLUMNで生成されたカラムを再定義するか、ALTER TABLE table_name RENAME COLUMN current_name TO new_nameを使用して既存のカラムの名前を変更してから新しい定義でADD COLUMNを呼び出します。

生成されたカラムはjson_extractのようなJSON関数に限定されるわけではありません。生成されたカラムがどのように生成されるかを定義するために、ほぼすべての利用可能な関数を使用できます。

例えば、前のsensor_readingテーブルのtimestampカラムに基づいてdateカラムを生成し、Unixタイムスタンプをデータベース内でYYYY-MM-dd形式に自動的に変換することができます:

ALTER TABLE your_table
-- date(timestamp, 'unixepoch')はUnixタイムスタンプをYYYY-MM-dd形式の日付に変換します
ADD COLUMN formatted_date AS (date(timestamp, 'unixepoch'))

または、将来の日付を計算するexpires_atカラムを定義し、その日付でクエリをフィルタリングすることもできます:

-- 生成されたカラムに基づいて「期限切れ」の結果をフィルタリングします:
-- SELECT * FROM your_table WHERE current_date() > expires_at
ALTER TABLE your_table
-- タイムスタンプから30日後の日付(YYYY-MM-dd)を計算します。
ADD COLUMN expires_at AS (date(timestamp, '+30 days'));

追加の考慮事項

  • テーブルには少なくとも1つの非生成カラムが必要です。生成カラムのみでテーブルを定義することはできません。
  • 式は同じテーブルおよび行内の他のカラムのみを参照でき、決定的関数のみを使用する必要があります。random()のような関数、サブクエリ、または集約関数は生成されたカラムを定義するために使用できません。
  • ALTER TABLE ... ADD COLUMNを介して既存のテーブルに追加されたカラムはVIRTUALでなければなりません。既存のテーブルにSTOREDカラムを追加することはできません。