PostgreSQL初心者ガイド!制約(主キー・外部キー・UNIQUE)を徹底解説
生徒
「PostgreSQL(ポストグレスキューエル)というのを使ってみようと思うのですが、データを入れるときに『変なデータが入らないように守る仕組み』があるって聞きました。それって何ですか?」
先生
「それは『制約(せいやく)』のことですね。データベースに保存するデータが、デタラメな内容にならないようにするためのルールのことです。例えば、会員名簿で同じIDの人が二人いたら困りますよね? そういう間違いを機械が自動で防いでくれるんですよ。」
生徒
「なるほど!間違えて消しちゃいけないデータを守ってくれたりもするんですか?」
先生
「その通りです!今日は、特によく使われる『主キー』『外部キー』『UNIQUE(ユニーク)制約』について、名簿を例に挙げてゆっくり見ていきましょう。」
1. データベースの「制約」とは何か?
PostgreSQLなどのリレーショナルデータベース(表形式でデータを管理するシステム)において、「制約」とは、テーブルに保存されるデータが守らなければならないルールのことです。 パソコンを触ったことがない方でも、「書類の記入漏れがないかチェックする窓口」をイメージすると分かりやすいでしょう。
もし制約がなかったら、名前が空欄のまま登録されたり、メールアドレスが重複して誰のものか分からなくなったりと、データベースの中身がめちゃくちゃ(整合性が失われた状態)になってしまいます。 これから紹介する3つの主要な制約を学ぶことで、正しく安全なデータベース設計の基礎が身に付きます。
エンジニアの必須スキル「SQL」を、 図解と豊富な練習問題でゼロから体系的に学びたい人へ。 MySQLやPostgreSQLなど、各種データベースに対応した不朽の入門書です。
SQL 第2版 ゼロからはじめるデータベース操作をAmazonで見る※ Amazon広告リンク
2. 主キー(PRIMARY KEY)でデータを特定する
主キー(しゅきー)は、その行が「世界に一つだけ」であることを保証するための最も重要な制約です。 例えば、学校の出席番号や、会社員であれば社員番号のようなものです。
主キーには2つの大きな特徴があります。
- 重複してはいけない: 同じ番号の人が二人いてはいけません。
- 空(NULL)であってはいけない: 番号が割り振られていない人は登録できません。
以下の「社員名簿(employees)」テーブルを見てみましょう。ここでは「id」を主キーとして設定しています。
id | name | department | join_date
---+----------+------------+------------
1 | 山田太郎 | 営業部 | 2023-04-01
2 | 佐藤花子 | 開発部 | 2023-05-15
3 | 鈴木一郎 | 総務部 | 2023-06-01
4 | 田中愛 | 営業部 | 2023-07-20
ここで、新しく「idが2」の人を追加しようとすると、PostgreSQLが「すでに2番は使われています!」とエラーを出して止めてくれます。
-- すでに存在するid=2を登録しようとする(エラーになります)
INSERT INTO employees (id, name, department, join_date)
VALUES (2, '高橋健二', '開発部', '2024-01-10');
実行結果は以下のようになります。
ERROR: duplicate key value violates unique constraint "employees_pkey"
DETAIL: Key (id)=(2) already exists.
このように、主キーを設定することで、データを1行ずつ確実に区別できるようになります。
3. UNIQUE制約で重複を防ぐ
UNIQUE(ユニーク)制約は、その列に「同じ値を二度と入れない」というルールです。 主キーと似ていますが、大きな違いは「主キーは1つのテーブルに1つだけ」ですが、UNIQUE制約は複数の列にかけることができます。
例えば、メールアドレスや電話番号です。社員番号とは別に、個人の連絡先が重複すると連絡ミスが起きてしまうため、UNIQUE制約を設定して守ります。
以下のテーブルでは、「email」列にUNIQUE制約がかかっています。
id | name | email | phone
---+----------+--------------------+--------------
1 | 山田太郎 | taro@example.com | 090-1111-1111
2 | 佐藤花子 | hanako@example.com | 090-2222-2222
3 | 鈴木一郎 | ichiro@example.com | 090-3333-3333
4 | 伊藤純 | jun@example.com | 090-4444-4444
誰かがすでに使っているメールアドレスで新しく登録しようとすると、エラーが発生します。
-- 佐藤花子さんと同じメールアドレスで登録しようとする
INSERT INTO employees_contacts (id, name, email)
VALUES (5, '渡辺修', 'hanako@example.com');
実行結果:
ERROR: duplicate key value violates unique constraint "unique_email"
このように、主キーではないけれど、中身が重なってほしくない情報に対してUNIQUE制約を使います。
4. 外部キー(FOREIGN KEY)でテーブル同士を繋ぐ
外部キー(がいぶきー)は、別のテーブルにあるデータと「紐付け(ひもづけ)」を行うための制約です。 これは「関連性のチェック」とも言えます。
例えば、「注文データ」と「商品リスト」を想像してください。商品リストに存在しない幽霊商品の注文が入ったら困りますよね。 外部キーを設定すると、「商品リストにある商品IDしか、注文データに入力できない」という制限をかけることができます。
まずは「部署(departments)」テーブルがあります。
dept_id | dept_name
--------+----------
10 | 営業部
20 | 開発部
30 | 人事部
次に、外部キーを設定した「社員(staff)」テーブルです。ここでの「dept_id」は部署テーブルを参照しています。
staff_id | name | dept_id
---------+----------+---------
101 | 山田 | 10
102 | 佐藤 | 20
103 | 鈴木 | 10
104 | 高橋 | 30
もし、存在しない「部署番号99」を無理やり登録しようとしたらどうなるでしょうか?
-- 部署テーブルに存在しない「99」を入れようとする
INSERT INTO staff (staff_id, name, dept_id)
VALUES (105, '田中', 99);
実行結果:
ERROR: insert or update on table "staff" violates foreign key constraint "staff_dept_id_fkey"
DETAIL: Key (dept_id)=(99) is not present in table "departments".
PostgreSQLが「そんな部署はありませんよ!」と怒ってくれました。 また、外部キーの凄いところは、「使われているデータを勝手に消させない」という機能もあります。 もし、営業部(10番)に所属している社員がいるのに、部署テーブルから営業部を削除しようとするとエラーになり、データの整合性を守ってくれます。
5. なぜ制約を使う必要があるのか?
プログラミング未経験の方は、「そんなに厳しくしなくても、気をつけて入力すればいいのでは?」と思うかもしれません。 しかし、システムを長く運用していると、人間の操作ミスは必ず起こります。
数万件、数十万件という膨大なデータを扱うとき、1つの間違いがシステム全体の故障に繋がることもあります。 PostgreSQLの制約は、いわば「データの防波堤」です。 あらかじめガッチリとルールを決めておくことで、将来のトラブルを未然に防ぎ、信頼性の高いシステムを作ることができるのです。
今回学んだ「主キー」「UNIQUE制約」「外部キー」は、どれもテーブル設計の基本中の基本です。 これらを組み合わせることで、整理整頓された美しいデータベースを構築できるようになります。