Skip to content

非公式本サイトは非公式の日本語ドキュメントであり、Cloudflare 公式サイトではありません。最新情報はdevelopers.cloudflare.comをご確認ください。

外部キーを定義する

最終更新 Markdown で表示Agent セットアップ

D1 では、データベース内のテーブルをまたいで外部キー制約を定義し、強制できます。

外部キー制約を使うと、テーブル間の関係を強制できます。たとえば、users テーブルの user_idorders テーブルの user_id を厳密に結びつけると、存在しないユーザーに対する注文は作成できません。

外部キー制約は、ほかのテーブルの行を参照している行の削除も防げます。たとえば、orders テーブルの行が参照している users テーブルの行は削除できません。

デフォルトでは、D1 はすべてのクエリとマイグレーションで外部キー制約が有効であることを強制します。これは、SQLite で各トランザクションに PRAGMA foreign_keys = on を設定したときと同じ動作です。

外部キー制約を遅延する

D1 データベースに対して クエリマイグレーション、または データのインポート を実行するとき、テーブル作成やスキーマ変更のあいだ、外部キー検証を無効にしたい場合があります。

D1 の外部キー強制は、SQLite の PRAGMA foreign_keys = on ディレクティブと同等です。D1 はすべてのクエリを暗黙のトランザクション内で実行するため、ユーザーのクエリからこの設定をクエリ中やマイグレーション中に変更することはできません。

代わりに、D1 では PRAGMA defer_foreign_keys = on または off を呼び出せます。これにより、現在のトランザクションが終わるまで、一時的に外部キー制約に違反できます。

PRAGMA defer_foreign_keys = off を呼び出しても、現在のトランザクションの外では外部キーの強制は無効になりません。トランザクションの終了時点で未解決の外部キー違反が残っていると、FOREIGN KEY constraint failed エラーで失敗します。

外部キーの強制を遅延するには、トランザクションの先頭、または制約に違反する変更の前に PRAGMA defer_foreign_keys = on を設定します。

-- Defer foreign key enforcement in this transaction.
PRAGMA defer_foreign_keys = on

-- Run your CREATE TABLE or ALTER TABLE / COLUMN statements
ALTER TABLE users ...

-- This is implicit if not set by the end of the transaction.
PRAGMA defer_foreign_keys = off

未解決の外部キー制約を解消した直後に、明示的に PRAGMA defer_foreign_keys = off を設定することもできます。まだ未解決の外部キー制約がある場合は、FOREIGN KEY constraint failed エラーが返り、違反を解消する必要があります。

外部キー関係を定義する

外部キー関係は、CREATE TABLE でテーブルを作成するとき、または ALTER TABLE で既存テーブルに列を追加するときに定義できます。

例として、2 つのテーブルを持つ e コマースサイトを考えます。

  • ユーザーアカウントの共通プロパティと、一意の user_id 識別子を定義する users テーブル。
  • 注文をユーザーテーブルの user_id に対応づける orders テーブル。

この対応づけは FOREIGN KEY として定義され、次を保証します。

  • 外部キー制約に違反する行を users テーブルから削除できません。有効なユーザーに対応づかない注文が残ることはありません。
  • orders は常に有効な user_id に対して定義されるため、無効(または存在しない)ユーザーを参照する注文を作るリスクを下げられます。
CREATE TABLE users (
    user_id INTEGER PRIMARY KEY,
    email_address TEXT,
    name TEXT,
    metadata TEXT
)

CREATE TABLE orders (
    order_id INTEGER PRIMARY KEY,
    status INTEGER,
    item_desc TEXT,
    shipped_date INTEGER,
    user_who_ordered INTEGER,
    FOREIGN KEY(user_who_ordered) REFERENCES users(user_id)
)

テーブルごとに複数の外部キー関係を定義でき、外部キー定義はデータベーススキーマ内の複数テーブルを参照できます。

外部キーのアクション

外部キー定義の一部として アクション を定義すると、親行(REFERENCES table(column))への変更を制限するか、伝播できます。アクションを定義すると、アプリケーションで外部キー制約の挙動を把握しやすくなり、関連データのクリーンアップや、データの孤立防止に役立ちます。

外部キー関係の ON UPDATE および / または ON DELETE 句には、5 つのアクションを設定できます。要件に応じて、ON UPDATEON DELETE に別々のアクションを定義することもできます。

  • CASCADE - 親キーの更新または削除で、関連するすべての子キー(行)を削除します。
  • RESTRICT - いずれかの子キーが参照している親キーは、更新も削除もできません。デフォルトの外部キー強制と異なり、RESTRICT を適用した関係はトランザクション終了時ではなく、すぐにエラーを返します。
  • SET DEFAULT - 外部キー定義が参照する子列を、スキーマで定義した DEFAULT 値に設定します。子列に DEFAULT が設定されていない場合、このアクションは使えません。
  • SET NULL - 外部キー定義が参照する子列を SQL の NULL に設定します。
  • NO ACTION - 何もしません。

次の例では、ON DELETE CASCADE を定義しているため、users テーブルからユーザーを削除すると、scores テーブルの関連行もすべて削除されます。削除したユーザーのスコアを残さない場合は、scores テーブルの関連行をすべて削除します。そうすると、まだ有効だったスコアを ほかの ユーザーが参照できなくなることがあります。

CREATE TABLE users (
    user_id INTEGER PRIMARY KEY,
    email_address TEXT,
)

CREATE TABLE scores (
    score_id INTEGER PRIMARY KEY,
    game TEXT,
    score INTEGER,
    player_id INTEGER,
    FOREIGN KEY(player_id) REFERENCES users(user_id) ON DELETE CASCADE
)

次のステップ

役に立ちましたか?