基礎

「山田太郎」の行が 4 つある (一意性)

定義

一意性制約 (unique constraint) とは、指定した列 (または列の組) の値がテーブル内で重複しないことを DBMS が構造的に保証する制約であり、主キーは NOT NULL と一意性を組み合わせた特殊な一意性制約として位置付けられる。

事故 — 「山田太郎」の行が 4 つある。同一人物?別 4 名?

1 年ぶりに戻ってきた山田太郎さんは、自分の EC アカウントを覚えていなかった。ログイン画面で試行錯誤の末に「新規登録」を選んだが、 以前使っていた email も思い出せない。とりあえず適当な文字列 (n/aunknown-) を入れて 3 回登録試行し、 いずれも登録は通ってしまった。翌週、顧客管理シートを見ると「山田太郎」が 4 行ある。

顧客管理シート — 「山田太郎」の行が 4 つ
顧客.xlsx
ABCD
1顧客ID顧客名メール登録日
2C-001山田太郎yamada@example.com2024-01-15
3C-011山田太郎n/a2025-11-01
4C-012山田太郎unknown2025-11-01
5C-013山田太郎-2025-11-01
6C-002佐藤花子sato@example.com2024-02-10
4 行は (a) 同姓同名の別 4 名か、(b) 1 人が 3 回追加登録した残骸か、システムからは判定できない

ここで先に確認しておきたい: 山田太郎という名前が 4 行あっても、それ自体は問題ない。 現実に同姓同名の別人は存在する。顧客ID (C-001 / C-011 / C-012 / C-013) は自動採番で unique なので、DB 的な UNIQUE(顧客ID) 制約は既に満たされている

では何が問題なのか。「山田太郎さんとして戻ってきたお客さんが、C-001 の再訪か、それとも別の新規 3 名か」を DB から判定できないことが問題。 マーケメールは 4 通全員に届き苦情が出た。「今月の新規顧客数」統計は3 名 増と報告されたが、実際は 0 (1 名の登録試行) だった可能性が高い。 カスタマーサポートに「私の注文履歴が見つからない」と問い合わせが殺到した。

原因 — 「識別に使うべき列」に UNIQUE 制約がない

Excel の顧客シートには、どの列に対しても 「絶対に重複させない」という宣言的な制約が無い。 顧客ID はプログラム側の自動採番で 結果的に unique になっているだけで、DB 側では何も保証していない。

本当に unique であるべきなのは、顧客を業務的に識別する属性 — つまり email や電話番号のような 「同じ人なら同じ値になる」自然キー。ここに UNIQUE 制約が掛かっていれば、山田太郎さんが 2 回目の登録を試みた時点でyamada@example.com の重複挿入としてシステムが弾ける。

surrogate key (顧客ID) の UNIQUE は「常に満たされる自明な条件」で、業務上ほとんど意味を持たない。 意味のある UNIQUE は 自然キー (email / phone / 会員番号) に掛ける必要がある。Excel にはこの区別が無いので、 surrogate key を unique にすればそれで満足してしまう構造になっている。

解決策 — 識別属性に UNIQUE + NOT NULL を宣言する

RDB では、テーブル定義時に 「この列は絶対に重複しない」「NULL 禁止」を宣言できる。 重複挿入は DBMS が拒否する。人間の運用に依存しない。

CREATE TABLE customers (
  id         BIGSERIAL PRIMARY KEY,     -- surrogate key: 自動採番で常に unique
  email      VARCHAR(255) NOT NULL,     -- 業務的な識別属性
  name       VARCHAR(50)  NOT NULL,
  created_at TIMESTAMPTZ  NOT NULL DEFAULT NOW(),

  -- 意味のある UNIQUE は「識別に使うべき列」に掛ける
  CONSTRAINT customers_email_key UNIQUE (email)
);

-- 山田太郎さんが 2 回目の登録を試みる → DBMS が拒否
INSERT INTO customers (email, name)
  VALUES ('yamada@example.com', '山田太郎');
-- ERROR: duplicate key value violates unique constraint "customers_email_key"

本記事の主題である 「一意性 = UNIQUE 制約」 はこれだけ。 「識別に使うべき列を選び、そこに UNIQUE を掛ける」がすべて。

補足: junk 値による回避と CHECK 制約

実は UNIQUE(email) だけでは、悪意なしのユーザーが n/aunknown- のような 異なる junk 文字列を毎回入れて再登録するのを防げない (それぞれが別の unique 値として通ってしまう)。 これを塞ぐには、email の 形式そのもの を検証する CHECK 制約 を併用する必要がある (CHECK / NOT NULL 制約は本シリーズ scope 外)。

UNIQUE と CHECK は別の制約であり、扱う概念も別 (前者は「値の重複禁止」、後者は「値の形式検証」)。 本記事はあくまで UNIQUE (一意性) に集中する。

「自然キー」vs「代理キー (サロゲートキー)」

主キーの候補は 2 種類:

  • 自然キー (natural key): 業務データそのもの (email、社員番号、ISBN)。 人間にとって意味があり、業務的な同一性を表現できる。だが値が変わる (email 変更、番号採番ルール変更) と参照が壊れる
  • 代理キー (surrogate key): 業務と無関係な連番や UUID (id 列)。 値が絶対に変わらないので参照が安定する。ただし「同じ人か違う人か」の情報は持たない

多くの実務では surrogate key を主キーに、自然キー (email 等) に UNIQUE 制約 の組み合わせを取る。 これで「参照の安定性」と「業務的な重複防止」を両立できる。

境界事例と実務判断

  • 同姓同名の別人: 名前を UNIQUE にしてはいけない (弾き過ぎる)。email や phone を UNIQUE にして、名前は普通の列にする
  • 家族で 1 email を共有: email UNIQUE だと 2 人目が登録できない。 複合 UNIQUE (email, name) や、phone を含む複合キーで対応する
  • NULL の扱いは DBMS で差がある: PostgreSQL / MySQL / Oracle は複数の NULL を許容、 SQL Server は 1 つの NULL のみ許容。UNIQUE 列は NOT NULL にする方が移植性が高い
  • 複合ユニーク: UNIQUE (order_id, product_id) で 「同じ注文の同じ商品は 1 行のみ」を保証。単一列 UNIQUE では表せない業務ルールを表現できる

関連トピック

主キー / UNIQUE の物理的な実装は UNIQUE インデックス を参照。キー設計そのものは キーの階層 で扱っている。

よくある疑問

Q.主キーと UNIQUE 制約はどう違う?
A.主キーは NOT NULL + 一意性の組で、テーブルに 1 つだけ設定できます。UNIQUE 制約は複数設定可能で NULL を許容します (多くの DBMS で NULL 重複は許容)。
Q.「同姓同名の別人」を扱いたい時はどう設計する?
A.名前を主キーにせず、代理キー (サロゲートキー、例: 連番 ID) を主キーにします。名前だけで判定しないよう業務側にも識別ルール (メール / 電話 / 生年月日) を定義します。
Q.UNIQUE 制約の NULL の扱いは DBMS でどう違う?
A.PostgreSQL / MySQL は複数の NULL を許容、Oracle も同様。SQL Server は 1 つの NULL のみ許容 (歴史的経緯)。移植性を考えるなら UNIQUE 列は NOT NULL にするのが安全です。
Q.複合ユニークとは?
A.複数列の組み合わせに対する UNIQUE 制約です。例: UNIQUE (order_id, product_id) で「同じ注文の同じ商品は 1 行のみ」を保証します。

もっと学びたい方へ(おすすめ書籍)

おすすめ
達人に学ぶDB設計徹底指南書 第2版
ミック

テーブル設計と正規化、パフォーマンス考慮のインデックス設計まで実務レベルで学べる定番書。第2版ではクラウド対応も強化。

Amazon で見る →
SQLアンチパターン 第2版
Bill Karwin

実務でやりがちなSQL・DB設計のアンチパターンとその回避策を体系的に学べる。

Amazon で見る →
情報処理教科書 データベーススペシャリスト 2025年版
三好康之

IPAデータベーススペシャリスト試験の総合対策書。インデックス関連は本サイトと合わせて学ぶと理解が深まる。

Amazon で見る →
おすすめ
楽々ERDレッスン (CodeZine BOOKS)
羽生章洋

ER 図をどう「使える設計」に落とすか、実務の判断まで踏み込んだ入門書。エンティティの切り出しから多対多の扱いまで具体例が豊富。

Amazon で見る →
達人に学ぶSQL徹底指南書 第2版
ミック

SQLの本質的な使い方と、インデックスが効くクエリの書き方を学べる。ウィンドウ関数など現代SQLも網羅。

Amazon で見る →
[改訂3版]内部構造から学ぶPostgreSQL
勝俣智成 ほか

PostgreSQLの内部構造・ストレージ・インデックス機構を丁寧に解説。設計と運用計画の鉄則が学べる。

Amazon で見る →
理論から学ぶデータベース実践入門
奥野幹也

リレーショナルモデルの理論から、インデックス設計を含む実務で使えるSQLまで解説。

Amazon で見る →

本セクションはAmazonアソシエイトのリンクを含みます。

オンライン個別指導

もっと深くDBを学びたい方へ。

たいてっくが、SQL・データベース設計・パフォーマンスチューニング・ IPAデータベーススペシャリスト対策まで、1対1で学習をサポートします。まずは無料相談から。

無料相談を予約する →
  • 教え方も上手で、お人柄も良いメンターです。DB周りの知識はもちろん、何より、しっかり教えてあげようという姿勢がとてもありがたかったです。データベース、SQLの学習を考えている方にはおススメです。
    H 様DB・SQL コース受講
  • 体系的に知識を教えてくださり、実際の業務でも大変役立っております。特に短い時間で効率よく知識の習得や、練習をできているのは期待以上でした。
    M 様DB・SQL コース受講
  • 大変充実したコンテンツでわかりやすいご説明をありがとうございました。基本的な質問にも丁寧にご説明いただき、また業務のご相談にも乗って頂き大変有意義な時間でした。
    K 様DB・SQL コース受講