データベースの制約まとめ
はじめに
多くのアプリケーションではデータベースを使用します。この時にデータベースに不適切なデータが登録されてしまうと、アプリケーション全体に悪影響を及ぼす可能性があります。例えば、存在しない日付や負の年齢など、想定外のデータによってエラーが発生する場合があります。したがって、そうならないように制約をきちんと設定し、データの整合性を保つことは重要です。今回はそんな制約についてあらためて整理し、まとめ直そうと思います。
制約とは
制約とは、テーブルの列に対して特定のルールを設定することで、誤ったデータの登録を防ぐ仕組みです。たとえば、「空のデータを許可しない」「重複を防ぐ」といった制限をかけることができます。これによって、データの整合性を保ち、信頼性のあるアプリケーションを構築することができます。今回は以下の5つについて解説していこうと思います。詳細は各項目で解説します。
- デフォルト値
- NOT NULL制約
- 一意性制約
- チェック制約
- 外部キー制約
デフォルト値
デフォルト値を設定すると、その列に値を設定しなかった場合にデフォルト値が入ります。例として以下のようになります。
<!-- テーブルの作成 -->
CREATE TABLE sampletable (
col1 varchar(30),
col2 int DEFAULT 100
);
<!-- データの挿入 -->
INSERT INTO sampletable (col1, col2) VALUES ('hoge', 40);
INSERT INTO sampletable (col1) VALUES ('huga');
<!-- テーブルの中身の確認 -->
SELECT * FROM sampletable;
テーブルの内容は以下の通りです。
col1 | col2
------+------
hoge | 40
huga | 100
NOT NULL制約
NOT NULL制約を設定すると列がNULLになりません。NULLにしようとするとエラーになります。例として以下のようになります
<!-- テーブルの作成 -->
CREATE TABLE sampletable (
col1 varchar(30),
col2 int NOT NULL
);
<!-- データの挿入 -->
INSERT INTO sampletable (col1) VALUES ('huga');
<!-- エラーメッセージ -->
ERROR: null value in column "col2" of relation "sampletable" violates not-null constraint
DETAIL: Failing row contains (huga, null).
一意性制約
一意性制約はUNIQUEで指定します。指定したら列の値がテーブル内にひとつしかないという制約になります。他の行に同じ値があるとエラーになります。
<!-- テーブルの作成 -->
CREATE TABLE sampletable (
col1 varchar(30),
col2 int UNIQUE
);
<!-- データの挿入 1回目は成功 -->
INSERT INTO sampletable (col1, col2) VALUES('hoge', 10);
<!-- データの挿入 2回目はエラー -->
INSERT INTO sampletable (col1, col2) VALUES('hoge', 10);
ERROR: duplicate key value violates unique constraint "sampletable_col2_key"
DETAIL: Key (col2)=(10) already exists.
チェック制約
チェック制約はCHECK(式)を使用します。式の評価結果が偽となる値は格納することができません。以下の例ではcol1が20以下のものは格納することができません。
<!-- テーブルの作成 -->
CREATE TABLE sampletable (
col1 int CHECK (col1 <= 20)
);
<!-- データの挿入 条件を満たしているので成功 -->
INSERT INTO sampletable (col1) VALUES (10);
<!-- データの挿入 条件を満たしていないのでエラー -->
INSERT INTO sampletable (col1) VALUES (40);
ERROR: new row for relation "sampletable" violates check constraint "sampletable_col1_check"
DETAIL: Failing row contains (40).
外部キー制約
指定したテーブルの指定した列に存在する値しか格納できないという制約です。FOREIGN KEYでテーブル内のカラムを指定し、REFERENCESで参照先のテーブルとカラムを指定します。指定したテーブルに存在しない値を指定するとエラーになります。また、他のテーブルから外部キー制約で参照されている値を消そうとしてもエラーになります。
<!-- テーブルの作成 -->
CREATE TABLE users (
id INT PRIMARY KEY,
name VARCHAR(50) NOT NULL
);
CREATE TABLE orders (
id INT PRIMARY KEY,
user_id INT,
order_date DATE NOT NULL,
FOREIGN KEY (user_id) REFERENCES users(id)
);
<!-- データの挿入 -->
INSERT INTO users (id, name) VALUES (1, 'Yamada');
<!-- user_id 1がusersテーブルに存在するので登録できる -->
INSERT INTO orders (id, user_id, order_date) VALUES (1, 1, '2025-01-07');
<!-- user_id 2がusersテーブルに存在しないので登録できない -->
INSERT INTO orders (id, user_id, order_date) VALUES (2, 2, '2025-01-07');
<!-- ordersテーブルから参照されているデータを削除しようとするとエラー -->
DELETE FROM users WHERE id=1;
ERROR: update or delete on table "users" violates foreign key constraint "orders_user_id_fkey" on table "orders"
DETAIL: Key (id)=(1) is still referenced from table "orders".
終わりに
今回は、データベースの制約に関して解説しました。データベースの制約を活用することで、データの整合性を保ち、アプリケーションの信頼性を向上させることができます。制約を正しく使うことで、データ品質を高め、開発時のバグや予期しない不具合を未然に防ぐことができます。今後の開発でデータベース設計をするときには、ぜひ、制約を意識してみてください。最後まで読んでいただきありがとうございました。
Discussion