[SQLのはじめ方] Part18: NOT NULL, UNIQUE, CHECK の使い方

SQL

テーブルに適切な制約を設定して、データの品質を保ちましょう💪

このページは、「Step 5: データ定義(DDL)と制約」の一部です。今回は、テーブル作成時に重要な役割を果たす NOT NULL, UNIQUE, CHECK という3つの制約について学びます。これらの制約を使いこなすことで、意図しないデータがデータベースに登録されるのを防ぎ、データの整合性を高めることができます。

1. NOT NULL制約: 値の入力を必須にする ✅

NOT NULL 制約は、その名の通り、カラムに NULL (値が存在しない状態) が入ることを禁止する制約です。ユーザーIDや必須の登録情報など、「必ず値が入っていてほしい」カラムに設定します。

基本的な使い方

CREATE TABLE 文でテーブルを作成する際に、カラム定義の後ろに NOT NULL を記述します。

CREATE TABLE users (
  user_id INT PRIMARY KEY,
  username VARCHAR(50) NOT NULL, -- ユーザー名は必須
  email VARCHAR(100) NOT NULL,    -- メールアドレスも必須
  register_date DATE
);

既存のテーブルに追加する

すでに存在するテーブルのカラムに NOT NULL 制約を追加することも可能です。ただし、追加する前にそのカラムに NULL 値が含まれていないか確認する必要があります。もし NULL が存在すると、制約の追加に失敗します。

構文はデータベース製品によって少し異なりますが、一般的には ALTER TABLE を使います。

PostgreSQL, SQL Serverなど:

ALTER TABLE users
ALTER COLUMN register_date SET NOT NULL;

MySQL:

ALTER TABLE users
MODIFY register_date DATE NOT NULL;

なぜ使うの? 🤔

  • データの完全性: 必須項目に値が必ず入ることを保証します。
  • 予期せぬエラー防止: アプリケーション側で NULL を想定していない場合に発生するエラーを防ぎます。
  • 検索の簡略化: NULL を考慮しない単純な条件で検索できる場合があります。(ただし、NULL の扱いは重要です! NULLの扱いとIS NULL/IS NOT NULL も参照してください。)
注意点: 既存のテーブルに NOT NULL 制約を追加する場合、対象カラムに NULL が含まれているとエラーになります。事前に UPDATE 文などで NULL を適切な値に置き換えるか、DEFAULT 値を設定するなどの対応が必要です。

2. UNIQUE制約: 値の重複を防ぐ 🔑

UNIQUE 制約は、指定したカラム(または複数のカラムの組み合わせ)に入る値が、テーブル内で一意(重複しない)であることを保証します。メールアドレスや商品コードなど、「他のレコードと同じ値であっては困る」カラムに使用します。

基本的な使い方

CREATE TABLE 文で、カラム定義の後ろに UNIQUE を記述するか、テーブル定義の最後に UNIQUE (カラム名) として指定します。

カラム定義で指定:

CREATE TABLE products (
  product_id INT PRIMARY KEY,
  product_code VARCHAR(20) UNIQUE, -- 商品コードはユニーク
  name VARCHAR(100) NOT NULL,
  price INT
);

テーブル定義の最後で指定(複数列も可能):

CREATE TABLE users (
  user_id INT PRIMARY KEY,
  username VARCHAR(50) NOT NULL,
  email VARCHAR(100),
  tel VARCHAR(15),
  UNIQUE (email),       -- メールアドレスはユニーク
  UNIQUE (tel)          -- 電話番号もユニーク (NULLは許容される場合あり)
);

-- 複数列の組み合わせでユニークにする場合
CREATE TABLE memberships (
  user_id INT,
  group_id INT,
  role VARCHAR(20),
  PRIMARY KEY (user_id, group_id),
  UNIQUE (user_id, role) -- 一人のユーザーは、一つのグループ内で同じ役割を持てない
);

既存のテーブルに追加する

ALTER TABLE を使って、既存のテーブルに UNIQUE 制約を追加できます。

ALTER TABLE products
ADD CONSTRAINT uq_product_code UNIQUE (product_code); -- 制約に名前を付けることも推奨

主キー (PRIMARY KEY) との違いは?

UNIQUE 制約と PRIMARY KEY (主キー) 制約は、どちらも値の一意性を保証しますが、以下の違いがあります。

特徴 UNIQUE制約 PRIMARY KEY制約
NULL値の許容 許容される(多くのDBで。ただし、NULL自体は1つまたは複数許容されるかはDBによる) 許容されない (NOT NULL が暗黙的に適用される)
テーブル内の数 複数設定可能 1つのみ設定可能
主な目的 特定のカラム(群)の値の重複を防ぐ テーブル内のレコードを一意に識別する

メールアドレスのように、「重複は困るけれど、登録時点では未入力 (NULL) も許したい」といった場合に UNIQUE 制約が役立ちます。

3. CHECK制約: 値の条件を指定する 🧐

CHECK 制約は、カラムに入力される値が特定の条件を満たしているかどうかをチェックします。条件に合わない値が INSERTUPDATE されようとすると、エラーが発生します。これにより、より細かいデータの妥当性を保証できます。

基本的な使い方

CREATE TABLE 文で、カラム定義やテーブル定義の際に CHECK (条件式) を記述します。

CREATE TABLE products (
  product_id INT PRIMARY KEY,
  name VARCHAR(100) NOT NULL,
  price INT CHECK (price >= 0),        -- 価格は0以上
  discount_rate REAL CHECK (discount_rate >= 0.0 AND discount_rate <= 1.0), -- 割引率は0.0~1.0の間
  status VARCHAR(10) CHECK (status IN ('active', 'inactive', 'discontinued')) -- ステータスは指定された文字列のみ
);

-- テーブルレベルでの制約 (複数のカラムを参照可能)
CREATE TABLE orders (
  order_id INT PRIMARY KEY,
  order_date DATE,
  ship_date DATE,
  CHECK (ship_date >= order_date) -- 出荷日は注文日以降
);

既存のテーブルに追加する

ALTER TABLE を使って、既存のテーブルに CHECK 制約を追加できます。

ALTER TABLE products
ADD CONSTRAINT chk_price CHECK (price >= 0); -- 制約に名前を付ける

どんな条件が使えるの? 💡

CHECK 制約の条件式では、以下のような演算子が利用できます。

  • 比較演算子: =, <> (または !=), >, <, >=, <=
  • 論理演算子: AND, OR, NOT
  • 範囲指定: BETWEEN
  • リスト指定: IN
  • パターンマッチ: LIKE (一部のDB)
  • その他、単純な算術演算や一部の関数(DB製品による制限あり)

例えば、「年齢は18歳以上」(age >= 18)、「性別は ‘male’ または ‘female’」(gender IN ('male', 'female')) といった具体的なルールをデータベースレベルで強制できます。

注意点:
  • CHECK 制約の条件式は、その行のデータだけで評価できる必要があります。基本的に他のテーブルを参照したり、結果が変わる可能性のある関数(例: NOW())の使用はできません。
  • NULL 値の扱いは少し特殊です。CHECK 制約の条件式が NULL と評価された場合(例えば NULL > 0)、制約違反とはみなされず、NULL の挿入や更新が許可されることがあります。

まとめ

今回は、データの整合性を保つための重要な制約、NOT NULL, UNIQUE, CHECK について学びました。

  • NOT NULL: 値が必須のカラムに設定し、NULL を禁止します。
  • UNIQUE: カラム(または組み合わせ)の値の重複を防ぎます。
  • CHECK: カラムの値が特定の条件を満たすことを保証します。

これらの制約を適切に使うことで、データベースに不正なデータや意図しないデータが入るのを防ぎ、アプリケーションの品質向上に繋がります。テーブルを設計する際には、各カラムにどのような制約が必要か、しっかり検討しましょう! 🎉

コメント

タイトルとURLをコピーしました