UNIQUE制約(カラムに格納される値がユニークな値かどうか)

テーブルを作成する時にカラムに対して UNIQUE 制約をつけると、カラムに重複した値を格納することができなくなります。ここでは PostgreSQL における UNIQUE 制約の使い方について解説します。

(Last modified: )

UNIQUE制約の使い方

テーブルを作成するとき、カラムに対して UNIQUE 制約を設定すると、カラムには重複した値を追加することができなくなります。書式は次のとおりです。

CREATE TABLE [ IF NOT EXISTS ] table_name (
  column_name data_type UNIQUE [, ... ]
)

また UNIQUE 制約はカラム毎ではなくテーブルに対して設定することもできます。

CREATE TABLE [ IF NOT EXISTS ] table_name (
  column_name1 data_type1, 
  column_name2 data_type2,
  [... ,]
  UNIQUE ( column_name [, ... ] )
)

カラムの定義と分けて記述したい場合や、複数のカラムの組み合わせに対して UNIQUE 制約を設定したい場合などに使用します。

なお UNIQUE 制約では NULL が複数格納されていても重複した値とは見なされません。

-- --

それでは実際に試してみます。 mydb データベースの myschema スキーマの中に次のようなテーブルを作成しました。

create table myschema.friends (
  name varchar(10) unique, 
  address varchar(10)
);

UNIQUE制約の使い方(1)

name カラムに UNIQUE 制約を設定していますので name カラムには重複した値を格納することはできません。

psql メタコマンドの \d コマンドを使って作成したテーブルのカラムの情報を取得してみます。

\d myschema.friends

UNIQUE制約の使い方(2)

テーブルに UNIQUE 制約を設定すると自動的にインデックスが作成されます。欄外に作成されたインデックスに関するインデックスの名前や対象となっているカラムに関する情報が表示されています。

自動で作成されたインデックスに関する情報を取得するには、 psql メタコマンドの \d コマンドを使います。引数に先ほど \d コマンドで表示されたインデックス名を指定して次のように実行してください。

\d myschema.friends_name_key

UNIQUE制約の使い方(3)

作成されたインデックスに関する情報が表示されました。

それではテーブルにデータを追加してみます。最初に次のようなデータを 3 つ追加しました。

insert into myschema.friends values
  ('Yamada', 'Tokyo'), 
  ('Kondo', 'Osaka'), 
  ('Kurita', 'Tokyo');

UNIQUE制約の使い方(4)

これらのデータは name カラムの値が重複していませんので問題なく追加できます。

次に name カラムの値として既にテーブルに格納されている値と同じ値を指定してデータを追加してみます。

insert into myschema.friends values ('Kondo', 'Kyoto');

UNIQUE制約の使い方(5)

UNIQUE 制約が設定されている name カラムに重複した値を追加しようとしたので ERROR: 重複キーが一意性制約"friends_name_key"に違反しています というエラーが表示されてデータの追加に失敗しました。

なお NULL は UNIQUE 制約が設定されているカラムに重複して格納してもエラーになりません。次のように name カラムの値が NULL のデータを 2 つ追加してみます。

insert into myschema.friends values
  (NULL, 'Nagoya'), 
  (NULL, 'Sapporo');

UNIQUE制約の使い方(6)

エラーとはならずにデータが正常に追加されました。

複数のカラムの組み合わせに対してUNIQUE制約を設定する

UNIQUE 制約は複数のカラムの組み合わせに対して設定することもできます。この場合、それぞれのカラムには重複した値が格納されていてもエラーとはなりませんが、対象のすべてのカラムの値の組み合わせが一致するデータは追加することができません。

複数のカラムの組み合わせに UNIQUE 制約を設定するにはテーブルに対する UNIQUE 制約の書式を使用します。

CREATE TABLE [ IF NOT EXISTS ] table_name (
  column_name1 data_type1, 
  column_name2 data_type2,
  [... ,]
  UNIQUE ( column_name [, ... ] )
)

-- --

それでは実際に試してみます。 mydb データベースの myschema スキーマの中に次のようなテーブルを作成しました。

create table myschema.friends (
  id integer, name varchar(10), 
  address varchar(10), 
  unique (name, address)
);

複数のカラムの組み合わせに対してUNIQUE制約を設定する(1)

name カラムと address カラムの組み合わせに UNIQUE 制約を設定していますので name カラムと address カラムの組み合わせが重複したデータは格納することはできません。

psql メタコマンドの \d コマンドを使って作成したテーブルのカラムの情報を取得してみます。

\d myschema.friends

複数のカラムの組み合わせに対してUNIQUE制約を設定する(2)

テーブルに UNIQUE 制約を設定すると自動的にインデックスが作成されます。欄外に作成されたインデックスに関するインデックスの名前や対象となっているカラムに関する情報が表示されています。

自動で作成されたインデックスに関する情報を取得するには、 psql メタコマンドの \d コマンドを使います。引数に先ほど \d コマンドで表示されたインデックス名を指定して次のように実行してください。

\d myschema.friends_name_address_key

複数のカラムの組み合わせに対してUNIQUE制約を設定する(3)

作成されたインデックスに関する情報が表示されました。

それではテーブルにデータを追加してみます。最初に次のようなデータを 3 つ追加しました。

insert into myschema.friends values
  (1, 'Yamada', 'Tokyo'), 
  (2, 'Kondo', 'Osaka'), 
  (3, 'Kurita', 'Tokyo');

複数のカラムの組み合わせに対してUNIQUE制約を設定する(4)

address カラムの値だけをみると重複したデータも追加されていますが、 name カラムと address カラムの組み合わせが同じデータはありませんので UNIQUE 制約でエラーとなることはありません。

次に name カラムと address カラムの組み合わせが既にテーブルに格納されている値と同じ値を指定してデータを追加してみます。

insert into myschema.friends values (4, 'Kondo', 'Osaka');

複数のカラムの組み合わせに対してUNIQUE制約を設定する(5)

UNIQUE 制約が設定されている name カラムと address カラムの組み合わせに重複した値を追加しようとしたので ERROR: 重複キーが一意性制約"friends_name_address_key"に違反しています というエラーが表示されてデータの追加に失敗しました。

なお NULL は UNIQUE 制約が設定されているカラムに重複して格納してもエラーになりません。次のように name カラムの値と address カラムにどちらか一つまたは両方のカラムの値が NULL で組み合わせが一致したデータを 2 つ追加してみます。

insert into myschema.friends values 
  (5, 'Ogata', NULL), 
  (6, 'Ogata', NULL);

複数のカラムの組み合わせに対してUNIQUE制約を設定する(6)

エラーとはならずにデータが正常に追加されました。

-- --

UNIQUE 制約の使い方について解説しました。

( Written by Tatsuo Ikura )

Profile
profile_img

著者 / TATSUO IKURA

プログラミングや開発環境構築の解説サイトを運営しています。