データベースの整合性を守る: PostgreSQL 外部キー完全ガイド
PostgreSQL 外部キー構文
基本的な構文
外部キー制約は、CREATE TABLE
または ALTER TABLE
ステートメントを使用して作成できます。
-- 子テーブル作成時に外部キー制約を定義
CREATE TABLE 子テーブル (
子テーブル_カラム1 型,
子テーブル_カラム2 型,
-- 外部キー制約
FOREIGN KEY (子テーブル_カラム2) REFERENCES 親テーブル (親テーブル_カラム)
);
-- 既存テーブルに外部キー制約を追加
ALTER TABLE 子テーブル
ADD FOREIGN KEY (子テーブル_カラム2) REFERENCES 親テーブル (親テーブル_カラム);
上記の例では、子テーブル
の 子テーブル_カラム2
は、親テーブル
の 親テーブル_カラム
に存在する値を参照する必要があります。
オプション
外部キー制約には、いくつかのオプションを指定できます。
- ON DELETE: 親テーブルのデータが削除された際に、子テーブルのデータにどのような処理を行うかを指定します。
CASCADE
: 親テーブルのデータが削除されると、子テーブルの関連するデータも削除されます。SET NULL
: 親テーブルのデータが削除されると、子テーブルの関連するデータの外部キーカラムはNULL
値に設定されます。
- ON UPDATE: 親テーブルのデータが更新された際に、子テーブルのデータにどのような処理を行うかを指定します。
NO ACTION
: 何もしません。
例
以下は、外部キー制約を使用した例です。
親テーブル products
CREATE TABLE products (
product_id SERIAL PRIMARY KEY,
product_name VARCHAR(255)
);
子テーブル orders
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
product_id INTEGER,
FOREIGN KEY (product_id) REFERENCES products (product_id)
);
この例では、orders
テーブルの product_id
は、products
テーブルの product_id
を参照する必要があります。
orders
テーブルに、products
テーブルに存在しないproduct_id
を挿入することはできません。
-- テーブル作成
CREATE TABLE products (
product_id SERIAL PRIMARY KEY,
product_name VARCHAR(255)
);
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
product_id INTEGER,
-- 外部キー制約
FOREIGN KEY (product_id) REFERENCES products (product_id)
-- ON DELETE CASCADE オプション
ON DELETE CASCADE
);
-- データ挿入
INSERT INTO products (product_name) VALUES ('商品1'), ('商品2');
INSERT INTO orders (product_id) VALUES (1), (2), (1);
-- 商品1を削除
DELETE FROM products WHERE product_id = 1;
-- 結果
-- orders テーブルから product_id が 1 のデータも削除される
-- 商品2を削除
DELETE FROM products WHERE product_id = 2;
-- 結果
-- orders テーブルから product_id が 2 のデータは削除されない
上記のコードを実行すると、以下の結果になります。
products
テーブルに2つの商品が登録されます。
PostgreSQL 外部キーを設定する他の方法
CHECK 制約
CHECK 制約を使用して、外部キー制約を間接的に設定できます。
CREATE TABLE 子テーブル (
子テーブル_カラム1 型,
子テーブル_カラム2 型,
-- CHECK 制約
CHECK (子テーブル_カラム2 IN (SELECT 親テーブル_カラム FROM 親テーブル))
);
CHECK 制約は外部キー制約よりも柔軟ですが、パフォーマンスが劣る場合があります。
トリガー
トリガーを使用して、外部キー制約を強制的に実行できます。
CREATE TRIGGER 子テーブル_トリガー
BEFORE INSERT ON 子テーブル
FOR EACH ROW
BEGIN
IF (
SELECT EXISTS (
SELECT 1 FROM 親テーブル
WHERE 親テーブル_カラム = NEW.子テーブル_カラム2
)
) THEN
-- INSERT 許可
ELSE
-- INSERT 拒否
END IF;
END;
上記の例では、子テーブル
にデータが挿入される前に、親テーブル
に存在する値かどうかを確認します。
トリガーは複雑なロジックを実装できますが、デバッグが難しい場合があります。
外部キー参照
CREATE TABLE 子テーブル (
子テーブル_カラム1 型,
子テーブル_カラム2 型,
-- 外部キー参照
FOREIGN KEY (子テーブル_カラム2) REFERENCES 親テーブル (親テーブル_カラム)
);
ALTER TABLE 子テーブル
ADD CONSTRAINT 子テーブル_FK FOREIGN KEY (子テーブル_カラム2) REFERENCES 親テーブル (親テーブル_カラム);
外部キー参照は視覚的な分かりやすさがありますが、機能的には他の方法と変わりません。
PostgreSQL 外部キー制約を設定するには、いくつかの方法があります。それぞれの方法にはメリットとデメリットがあり、状況に応じて最適な方法を選択する必要があります。
sql postgresql foreign-keys