エンティティと属性
エンティティと属性 とは
データベースの基本要素、エンティティと属性をSQLで操作します。本レッスンでは、エンティティと属性 の基本から実際の使いどころまでを整理し、現場で迷わず使える形に落とし込みます。
なぜ重要か
テーブル設計の良し悪しは、ほぼ 「エンティティの切り方」 と 「属性の置き場所」 で決まります。エンティティの切り方を間違えると、後で 2 つのテーブルに分割する大きなマイグレーションが必要になります。属性を間違ったエンティティに置くと、データの重複や更新異常が発生します。本レッスンでは、エンティティ と 属性 をどう見極めるか、その判定基準をしっかり学びます。これは正規化(次章)の土台にもなる、設計の中核となるスキルです。
エンティティとは
エンティティ とは、業務の中で 「個別に識別したい物事」 のことです。例えば EC サイトなら「ユーザ」「商品」「注文」など。エンティティは「物理的なモノ」だけでなく、「イベント」(注文・予約・ログイン履歴)や「概念」(カテゴリ・タグ)も含みます。
判別の目安は次の通りです。
- 個別に一意な ID を付けたいか — はい → エンティティ候補
- 削除・更新の単位として扱いたいか — はい → エンティティ候補
- 業務の人がその名前で会話しているか — はい → エンティティ候補
属性とは
属性 は、エンティティが持つ性質や値です。テーブルでいうと 列 に相当します。属性には大きく次の 3 種類があります。
| 種類 | 例 | 説明 |
|---|---|---|
| 識別属性 | id, code | エンティティを一意に識別する |
| 記述属性 | name, price, created_at | エンティティの性質を表す |
| 関連属性 | user_id (FK) | 他エンティティとの関連を表す |
ステップごとの動作
エンティティと属性の関係を ER図 で表すと、四角形の中に属性のリストが入る形になります。下図は「ユーザ」「住所」「商品」を例にした 論理モデル です。
注目すべき設計判断は、「住所」を users の列にせず、別エンティティ addresses テーブルに分けたことです。一人のユーザが複数の住所(自宅・職場・配送先)を持つなら、列の繰り返し(postal_code_1, postal_code_2…)ではなく別テーブルにすべきです。これは 属性の繰り返しが見えたらエンティティ化を検討するサイン という典型例です。
代表例
設計の良し悪しを比較します。まず 悪い例 から見ましょう。
SQL クエリ
-- 悪い例: 住所がユーザ列に詰め込まれている
CREATE TABLE users_bad (
id INT PRIMARY KEY,
name TEXT NOT NULL,
address1 TEXT,
address2 TEXT,
address3 TEXT
);3 個までしか住所を持てず、4 個目を追加するには ALTER TABLE が必要です。users_bad のように address1〜address3 を並べる設計は破綻のサインです。NULL も多くなり、住所の検索(市区町村で絞り込む等)も難しくなります。
SQL クエリ
-- 良い例: 住所を別エンティティに分離
CREATE TABLE users (
id INT PRIMARY KEY,
name TEXT NOT NULL
);
CREATE TABLE addresses (
id INT PRIMARY KEY,
user_id INT NOT NULL,
label TEXT NOT NULL,
postal_code TEXT NOT NULL,
city TEXT NOT NULL
);住所が何個でも追加でき、検索もできるようになります。これが「属性をエンティティに昇格させる」設計判断です。
この設計を SQL で確認すると、各ユーザの「登録住所件数」を求めることができます。
SQL クエリ
SELECT u.name, COUNT(a.id) AS address_count
FROM users u
LEFT JOIN addresses a ON a.user_id = u.id
GROUP BY u.id, u.name
ORDER BY u.id;よくある落とし穴
属性が繰り返し列(
*_1, *_2, *_3)になったら設計を見直すサイン。ほぼ間違いなく、別エンティティに分けたほうが綺麗になります。最大数を「3 つで十分」と決め打ちすると、必ず数年後に拡張要件が来て破綻します。
「導出可能な属性」は基本的に持たない。例えば
tax_included_priceはpriceと税率から計算できるので、列として持たずビューや式で計算するのが原則です。持つ場合は、更新タイミングを厳密に管理する覚悟が必要です。
まとめ
- エンティティは「個別に識別したい物事」、属性はその性質や関連
- 属性は識別属性・記述属性・関連属性の 3 種類に分けて整理する
- 属性が繰り返し列になったら、エンティティに昇格させる
- 導出可能な値は原則として列で持たない
- 設計の良し悪しは、ここの判断で 8 割が決まると言ってよいほど重要なステップ
次のレッスン
次は リレーションシップとカーディナリティ です。データベースのリレーションシップとカーディナリティの概念について解説します。
事前確認 — 進む前に次の 3 つができることを確認しましょう。
- エンティティと属性 の要点を自分の言葉で説明できる
- このレッスンの最小コード (または操作手順) を見ずに書ける
- 練習問題やクイズで間違えた箇所を読み直して理解した
理解度チェック (30 秒)
Q. エンティティと属性 とは何か、1 文で説明してください。
A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。
関連レッスン
テーブル構造
schema.sql
CREATE TABLE users (
id INT PRIMARY KEY,
name TEXT NOT NULL
);
CREATE TABLE addresses (
id INT PRIMARY KEY,
user_id INT NOT NULL,
label TEXT NOT NULL,
postal_code TEXT NOT NULL,
city TEXT NOT NULL
);
INSERT INTO users (id, name) VALUES
(1, '田中'),
(2, '鈴木'),
(3, '佐藤');
INSERT INTO addresses (id, user_id, label, postal_code, city) VALUES
(1, 1, '自宅', '100-0001', '東京都千代田区'),
(2, 1, '職場', '150-0002', '東京都渋谷区'),
(3, 1, '実家', '530-0001', '大阪市北区'),
(4, 2, '自宅', '231-0001', '横浜市中区'),
(5, 2, '職場', '100-0001', '東京都千代田区');期待される出力
| name | address_count |
|---|---|
| 田中 | 3 |
| 鈴木 | 2 |
| 佐藤 | 0 |