SQL制約: PRIMARY KEY、FOREIGN KEY、UNIQUE、CHECK

PRIMARY KEY、FOREIGN KEY、UNIQUE、CHECK、NOT NULLなどのSQL制約をマスター。データベーススキーマ定義でデータ整合性ルールを直接適用する方法を解説します。

DDL

詳細な説明

SQL制約: PRIMARY KEY、FOREIGN KEY、UNIQUE、CHECK

制約はテーブルのデータにルールを適用し、データベースレベルで精度、一貫性、整合性を保証します。無効なデータに対する最後の防御線です。

PRIMARY KEY

各行を一意に識別します。UNIQUEとNOT NULLの組み合わせです:

CREATE TABLE users (
  id SERIAL PRIMARY KEY,
  email VARCHAR(255) NOT NULL
);

-- 複合主キー
CREATE TABLE order_items (
  order_id INTEGER,
  product_id INTEGER,
  quantity INTEGER NOT NULL,
  PRIMARY KEY (order_id, product_id)
);

FOREIGN KEY

テーブル間の参照整合性を強制します:

CREATE TABLE orders (
  id SERIAL PRIMARY KEY,
  customer_id INTEGER NOT NULL,
  FOREIGN KEY (customer_id) REFERENCES customers(id)
    ON DELETE RESTRICT
    ON UPDATE CASCADE
);

参照アクション:

  • CASCADE: 変更を子行に伝播する
  • RESTRICT: 子行が存在する場合に操作を禁止する
  • SET NULL: 外部キーカラムをNULLに設定する
  • SET DEFAULT: カラムのデフォルト値に設定する

UNIQUE

カラムまたはカラムの組み合わせのすべての値が一意であることを保証します:

ALTER TABLE users ADD CONSTRAINT uq_email UNIQUE (email);

-- 複数カラムのユニーク制約
ALTER TABLE subscriptions
ADD CONSTRAINT uq_user_plan UNIQUE (user_id, plan_id);

UNIQUEはほとんどのデータベースで複数のNULLを許可しますが、PRIMARY KEYはNULLを一切許可しません。

CHECK

値がブール式を満たすことを検証します:

CREATE TABLE products (
  id SERIAL PRIMARY KEY,
  name VARCHAR(100) NOT NULL,
  price DECIMAL(10,2) CHECK (price > 0),
  discount DECIMAL(3,2) CHECK (discount BETWEEN 0 AND 1),
  start_date DATE,
  end_date DATE,
  CONSTRAINT valid_dates CHECK (end_date > start_date)
);

NOT NULL

最もシンプルな制約で、NULL値を防ぎます:

ALTER TABLE orders ALTER COLUMN status SET NOT NULL;

ベストプラクティス

  • 可能な限りCREATE TABLE時に制約を定義し、後から追加するのではなく
  • より明確なエラーメッセージとマイグレーション管理のために、すべての制約に明示的な名前を付ける
  • 変更される可能性が低いビジネスルールにはCHECK制約を使用する
  • 参照整合性を維持するために常に外部キーを追加する
  • 高ボリュームの書き込み操作における外部キーのパフォーマンスへの影響を考慮する

制約は、どのアプリケーションがテーブルに書き込んでも無効なデータを防ぐ信頼性の高いデータベースの構築に不可欠です。

ユースケース

マルチテナントSaaSプラットフォームが、CASCADE削除付き外部キー、テナントごとのメールのUNIQUE制約、サブスクリプション日付のCHECK制約を使用して、サービス全体のデータ整合性を確保する場面。

Try It — SQL Formatter

フルツールを開く