🥽

データベースの制約まとめ

2025/01/08に公開

はじめに

多くのアプリケーションではデータベースを使用します。この時にデータベースに不適切なデータが登録されてしまうと、アプリケーション全体に悪影響を及ぼす可能性があります。例えば、存在しない日付や負の年齢など、想定外のデータによってエラーが発生する場合があります。したがって、そうならないように制約をきちんと設定し、データの整合性を保つことは重要です。今回はそんな制約についてあらためて整理し、まとめ直そうと思います。

制約とは

制約とは、テーブルの列に対して特定のルールを設定することで、誤ったデータの登録を防ぐ仕組みです。たとえば、「空のデータを許可しない」「重複を防ぐ」といった制限をかけることができます。これによって、データの整合性を保ち、信頼性のあるアプリケーションを構築することができます。今回は以下の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