整合性制約のタイプ

主キー制約 / プライマリキー

表の各行を完全に一意に識別できるカラムまたはカラム集合であり、すべてのカラムに NULL を含まない。 識別するということは、例えば会員を管理する場合の会員番号をあらわす。

主キーは原則として、変更しない項目の集合であることが望ましい。 また、主キーには表のリレーションを行なうという重要な役割もある。 そして、1 つの表に 1 つしか定義できない。
参考 ⇒ テーブル定義の変更(列の追加、変更、削除)

主キー以外の主キーになり得るキーの集まりは候補キー、そして、一意となるすべてのパターンはスーパーキーと呼ばれる。 キーにはエンティティ本来がもつ自然キー (ナチュラルキー)とデータベースによって発番して管理する代替キー(サロゲートキー)がある。

複合主キー / 複合プライマリキー

主キーで複数のカラムから構成されていることを強調したい場合には特別に複合主キーと呼ぶことがある。また複合主キー(複合インデックス)におけるカラムの定義の順序は制約としての差異はないため重要ではないが、検索パフォーマンスには非常に重要項目であり順番によって大きな影響を与えるため、よく吟味してから順番を選定する。複合キーは種類によって異なるが単一ブロックに格納できる必要があり、最大で約 30 カラムまでの複合キーを作成できる。
参考 ⇒ B-Tree インデックス

一意キー制約 / ユニークキー

表の NULL 以外の各行を一意に制約する。しかし NULL 値を許容するため、値なしの状態が複数存在することは許される。

一意キー制約と NULL

単一の列で構成される一意キーの場合は、複数のNULL(行) を持つことが可能。
複合一意キーにおいてすべてのキー列に対して NULL を持つ行も同様に複数持つことが可能。
ただし、1つ以上のキー列に対して NULL を持ち、その他のキー列に対して同じ組合せの値を持つ 2つの行は制約違反となる。(※)
一意キーは 1 つの表に 複数定義してもよい。

つまり

  • 単一列における一意キー制約において NULL が存在して NULL を INSERT してもは制約に違反しない。
  • 複合列における一意キー制約において
    (NULL,NULL) ⇔ (NULL,NULL) は制約に違反しないが 
    (NULL,1000) ⇔ (NULL,1000) は一意キー制約違反となる。
    (1000,NULL,NULL) ⇔ (1000,NULL,NULL) も同様に違反となる。 (※)

(※) 複合列における一意キー制約での、この振る舞いは Oracle 検索メカニズムによるものとマニュアルに書かれている。標準SQL では制約の 「1つのキー列でも NULL を持つ」場合には制約違反にはならない。という定義のようである。(標準SQL の資料が見つからなかったので未確認:制定年によって内容も変化する)

RDBMS によって実装レベルに差があるため要注意である。SQL-Server では単一列でも制約違反となり、PostgreSQL では標準SQL に準拠しているらしい。

プライマリキーとユニークキーの違い

プライマリキーとユニークキーの違いは 「確実に 識別する(identification) ための 主たる制約」 と 「NULL 以外の行が 一意であることを保証する(uniqueness) ための その他の制約」 という違いがある。
さらに原則的にキーの値を変更を許可するかしないかという面もある。 人間にとっては意味論的に異なるものであるが Oracle データベースにしてみれば、その内部の仕組みに大きな差はない。

例としては、ある顧客を会員番号を主キーとして管理している場合に (本籍)住所、氏名、生年月日のカラムの組み合わせが一意キーとして考えられる。
通常、この組み合わせのキーは一意である*1が変更可能であることに大きな違いがある。そして、これらの組み合わせを使ったテーブルのリレーションは好ましいものではない。
一方、主キー(会員番号)は退会処理などを特別な処理しない限りは変更されることはない。不可能ではないが原則、変更不可能という位置づけである。

キー制約とインデックスの関係

主キー制約および一意キー制約を定義すると同時にユニークインデックスが作成される(※)が、 DBMS(Oracle)の実装に関するもので、主「キー」とユニーク「インデックス」はそもそも観点の異なる存在である。
すなわち、主キーや一意キーによるアクセスにユニークインデックスを使用できることは RDBMS 製品の固有の機能実装における副産物であり SQLの規格には定義されていない。

(※) 既に代替できるインデックスがあればそれを使い、遅延制約 を選択している場合には NONUNIQUE インデックスが作成される。

[NOT] NULL 制約

NULL をデータとして許可する/しない
デフォルトは NULL を設定可能(⇔ NOT NULL) 、厳密には制約ではなく NULL 許可(NULLABLE)。

NULL とインデックス

Oracle では B-Tree インデックスに NULL 値は格納されない。IS NULL 条件はテーブルフルスキャンされる。
一方、ビットマップインデックスでは一般的には NULL を含んでインデックスに格納されるため、IS NULL 条件でも インデックスの使用が可能となる。
Oracle 10g 限定でかつ where にしか記述できないが将来面白そうな NULL(UNKNOWN)を扱う関数が出てきている。
LNNVL 関数

CHECK 制約

テーブルのレコードに条件を設定し、条件に一致しているものを許可する。
例) IS_VALIDATE に NULL(=UNKNOWN) , 0(=FALSE), 1(=TRUE)を許可する。

CREATE TABLE (
  IS_VALIDATE NUMBER(1)
  CONSTRAINTS constraint_name CHECK (IS_VALIDATE IN ('1', '0'))
) ;

外部制約・外部キー制約

表のキーの値について、関連する表のキーの値と一致する場合にデータとして許可する。
表と表の論理的な関連付けを行い外部キーに対して値(親キー)が存在することを保証する。
外部キーには、親表の値もしくは NULL を持つことが可能。
外部キーの親キーは主キーもしくは一意キーでなければならない。

  • NO ACTION(デフォルト):参照先のデータの更新または削除を禁止する(文の最後にチェック)
  • RESTRICT:参照先のデータの更新または削除を禁止する
  • SET NULL: 参照先が更新、削除されると対応する依存データがすべて NULL に設定
  • SET DEFAULT: 参照先が更新、削除されると対応する依存データがすべてデフォルト値に設定(Oracle では更新 + SET DEFAULT は無い)
  • CASCADE: 参照先が更新されると更新、削除されると削除


関連事項

日本オラクル
■ 日本オラクル 株式会社
■ オラクルマスター資格 (オラクルマスターとは
■ 会員制(無料)の公式技術サイト

*1 一意で無い場合が考えられるならば、さらに条件をつければよい