📌

テーブル設計で混同しやすいキーとドメインを整理する

に公開

まず結論

テーブル設計の議論では、「値が一意になる列」と「主キー」を同じ意味で使わないことが大切です。最低限、次の関係を押さえておくと会話がずれません。

サロゲートキーは「業務上の意味を持たない、識別用に導入したキー」という性質の分類です。主キーや候補キーと排他的な概念ではありません。

使う場面

次のような設計レビューで用語の区別が効きます。

  • メールアドレスを主キーにするか、連番 ID を置くか
  • 複合ユニーク制約が本当に業務上の一意性を表すか
  • コード値の形式を列ごとに重複定義してよいか
  • 外部キーが参照する識別子を変更可能にしてよいか

構文と設定項目

用語 意味
スーパーキー 行を一意に識別できる属性の集合。余分な属性を含んでもよい {顧客ID, 氏名}
候補キー どの属性を除いても一意性を失う、最小のスーパーキー {顧客ID}{メールアドレス}
主キー 候補キーから主たる識別子として選んだもの {顧客ID}
代替キー 候補キーのうち主キーに選ばなかったもの {メールアドレス}
複合キー 複数の属性で構成するキー {契約ID, 明細番号}
ナチュラルキー 業務上すでに意味を持つ属性を使うキー 証券コードなど
サロゲートキー 識別のためにシステムが追加する、業務上の意味を持たないキー UUID、採番ID
外部キー 別表または同じ表のキーを参照し、参照整合性を表すもの 注文の顧客ID

スーパーキーの個数を列数だけから求めることはできません。どの属性集合が一意になるかは、データの制約に依存するためです。

ドメイン

ドメインは、属性が取り得る値の集合です。DBMS の DOMAIN 機能を使う場合は、基礎型に制約を加えた再利用可能な型として定義します。

CREATE DOMAIN positive_amount AS numeric(18, 2)
  CHECK (VALUE >= 0);

同じ varchar(10) でも、郵便番号と商品コードは別のドメインです。物理型が同じだから同じ意味、とは限りません。

実装例

顧客の識別に採番 ID を使い、メールアドレスの業務上の一意性も守る例です。

CREATE TABLE customer (
  customer_id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  email       varchar(254) NOT NULL,
  name        varchar(100) NOT NULL,
  CONSTRAINT uq_customer_email UNIQUE (email)
);

ここでは customer_id がサロゲートキーかつ主キー、email が代替キーです。ただし、メールアドレスの大文字小文字や変更履歴をどう扱うかで制約は変わります。業務ルールを先に決める必要があります。

つまずきやすい点

一意に見える値をすぐ主キーにする

電話番号やメールアドレスは変更されます。外部参照が多い場合、変更可能な値を主キーにすると更新範囲が広がります。

サロゲートキーを置いて業務上の一意性を忘れる

採番 ID を追加しても、重複登録を防ぐ業務制約は消えません。必要な候補キーには UNIQUE 制約を置きます。

NULLを含む一意制約の挙動を決めない

NULL と一意制約の扱いは DBMS や定義方法で差があります。対象 DBMS で検証し、要件に合わなければ部分インデックスなどを検討します。

関連する機能

まとめ

主キーは候補キーから選び、候補キーは最小のスーパーキーです。ナチュラルキーとサロゲートキーはキーの由来を表します。役割と性質を分けて話すと、制約の抜けや不要な結合を減らせます。

Discussion