💬

ユニーク制約とユニークインデックス

に公開

カラムの値がユニークになるようにするときに、「"ユニーク制約"をつけよう」なんていう言い方をしていたが、この"ユニーク制約"が具体的に何を指しているか、意外にちゃんと把握してなかった
※postgreSQLのお話

そもそもユニークはどうやって実現されているのか

postgreSQLにおいて、値のユニークさはユニークインデックスで実現されている
11.6. 一意インデックス #

ユニークインデックスがあるカラムに対してデータを挿入/更新する場合、
ユニークインデックス上に同じ値がないかを確認する。
問題がなければデータ処理がそのまま進む。

ユニークインデックスを作るためには

ユニークインデックスを作る場合、二つの方法がある。

  • ユニーク制約を追加する
  • ユニークインデックスを直接作成する

ユニーク制約

出ました「ユニーク制約」
postgreSQLにおいて、「ユニーク制約」とは、pg_constraintsテーブルに格納されてる制約データのことを指します
制約

// テーブル作成時
CREATE TABLE products (
    product_no integer UNIQUE,
    name text,
    price numeric
);

// あとで追加
ALTER TABLE users
ADD CONSTRAINT users_email_key UNIQUE (email);

pg_constraintsにユニーク制約を追加すると、ユニークインデックスも自動で作成されます

ユニークインデックスを直接作る

ユニークインデックスを作るクエリはこんな感じ

CREATE UNIQUE INDEX name ON table (column [, ...]);

これはpg_constraintsに制約は追加しないで、ユニークインデックスだけを作ってくれる。

Railsの場合

Railsでユニーク性を担保したい場合は、こんな感じで書くことが多い

add_index :テーブル名, :カラム名, unique: true

これはユニーク制約を追加してるわけではなくて、ユニークインデックスを直接作成してる

どっちでユニークを実現するべき?

ネットで調べたり、AIに聞いたりしたけどあんまよくわかんなかった。
とりあえず、ユニーク制約があるというルールをDBで明示的にしておきたい場合は、pg_constraintsに追加した方が良いらしい。
追加しておくことでスキーマに明記され、DB移行時などにルールが漏れることがなくなるとか。

まとめ

ユニーク制約とは、カラムの値のユニークさを担保するルールを指し、pg_constraintsというテーブルに保存されている。

ユニークインデックスとは、実際に値がユニークであるかどうかを判定するためのインデックスを指す。

Discussion