エンティティと属性

エンティティと属性 とは

データベースの基本要素、エンティティと属性をSQLで操作します。本レッスンでは、エンティティと属性 の基本から実際の使いどころまでを整理し、現場で迷わず使える形に落とし込みます。

なぜ重要か

テーブル設計の良し悪しは、ほぼ 「エンティティの切り方」「属性の置き場所」 で決まります。エンティティの切り方を間違えると、後で 2 つのテーブルに分割する大きなマイグレーションが必要になります。属性を間違ったエンティティに置くと、データの重複や更新異常が発生します。本レッスンでは、エンティティ属性 をどう見極めるか、その判定基準をしっかり学びます。これは正規化(次章)の土台にもなる、設計の中核となるスキルです。

エンティティとは

エンティティ とは、業務の中で 「個別に識別したい物事」 のことです。例えば EC サイトなら「ユーザ」「商品」「注文」など。エンティティは「物理的なモノ」だけでなく、「イベント」(注文・予約・ログイン履歴)や「概念」(カテゴリ・タグ)も含みます。

判別の目安は次の通りです。

  • 個別に一意な ID を付けたいか — はい → エンティティ候補
  • 削除・更新の単位として扱いたいか — はい → エンティティ候補
  • 業務の人がその名前で会話しているか — はい → エンティティ候補

属性とは

属性 は、エンティティが持つ性質や値です。テーブルでいうと に相当します。属性には大きく次の 3 種類があります。

種類説明
識別属性id, codeエンティティを一意に識別する
記述属性name, price, created_atエンティティの性質を表す
関連属性user_id (FK)他エンティティとの関連を表す

ステップごとの動作

エンティティと属性の関係を ER図 で表すと、四角形の中に属性のリストが入る形になります。下図は「ユーザ」「住所」「商品」を例にした 論理モデル です。

diagram (will load when visible)

注目すべき設計判断は、「住所」を 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 のように address1address3 を並べる設計は破綻のサインです。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_priceprice と税率から計算できるので、列として持たずビューや式で計算するのが原則です。持つ場合は、更新タイミングを厳密に管理する覚悟が必要です。

まとめ

  • エンティティは「個別に識別したい物事」、属性はその性質や関連
  • 属性は識別属性・記述属性・関連属性の 3 種類に分けて整理する
  • 属性が繰り返し列になったら、エンティティに昇格させる
  • 導出可能な値は原則として列で持たない
  • 設計の良し悪しは、ここの判断で 8 割が決まると言ってよいほど重要なステップ

次のレッスン

次は リレーションシップとカーディナリティ です。データベースのリレーションシップとカーディナリティの概念について解説します。

事前確認 — 進む前に次の 3 つができることを確認しましょう。

  1. エンティティと属性 の要点を自分の言葉で説明できる
  2. このレッスンの最小コード (または操作手順) を見ずに書ける
  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', '東京都千代田区');

期待される出力

nameaddress_count
田中3
鈴木2
佐藤0

ヒント

query.sql
query.sql
学習モード
コードの実行結果
データベースを初期化中...