第3部:ドキュメントスキル / 第5章:データベース操作

テーブル定義書の読み方

テーブル定義書は、データベースのテーブル構造を定義したドキュメントです。SQL作成やデータ操作で必ず参照します。

📖 読了目安 約20分 対象:テーブル定義書を読み、データベース設計を理解したい方

テーブル定義書とは

役割

  • テーブル(データの入れ物)の構造を定義
  • カラム(列)の仕様を定義
  • 制約(主キー、外部キーなど)を定義
  • インデックス(検索高速化)を定義

いつ使うか

SQL作成時カラム名、型の確認
実装時データ構造の理解
テスト時データ確認
障害調査時データの追跡

テーブル定義書の構成

よくある構成要素

項目内容確認ポイント
テーブル名物理名・論理名命名規則
カラム定義各列の詳細型、桁数、NULL
主キーレコードを一意に識別どのカラムか
外部キー他テーブルとの関連参照先
インデックス検索高速化どのカラムに
備考補足情報運用ルール

カラム定義の要素

項目内容確認すること
カラム名(物理名)実際のDB名英数字、命名規則
カラム名(論理名)日本語名何のデータか
データ型VARCHAR, INTなど格納できるデータ
桁数最大文字数/精度入力値の制限
NULLNULL許可/不可必須かどうか
デフォルト初期値未指定時の値
備考補足説明注意事項

よく使うデータ型

文字列型

説明使い分け
CHAR(n)固定長文字列桁数が決まっているもの(郵便番号など)
VARCHAR(n)可変長文字列一般的な文字列
TEXT長い文字列備考、説明文など

数値型

説明使い分け
INT整数ID、数量など
BIGINT大きい整数大きなID、カウンターなど
DECIMAL(p,s)固定小数点金額など精度が必要なもの
FLOAT浮動小数点計算結果など

日時型

説明使い分け
DATE日付生年月日など
TIME時刻開始時刻など
DATETIME / TIMESTAMP日時作成日時、更新日時など

【サンプル】テーブル定義書の実例

usersテーブル定義書

基本情報

テーブル名(物理)users
テーブル名(論理)ユーザー
スキーマpublic
説明サービス利用者の情報を管理
作成日2024/01/15
更新日2024/02/01

カラム定義

No物理名論理名データ型桁数NULLPKFKデフォルト備考
1idユーザーIDBIGINT-×-AUTO自動採番
2emailメールアドレスVARCHAR256×---ユニーク
3password_hashパスワードVARCHAR256×---bcryptハッシュ
4name氏名VARCHAR100×----
5phone電話番号VARCHAR15--NULLハイフン含む
6statusステータスINT-×--11:有効, 2:停止, 9:退会
7last_login_at最終ログイン日時DATETIME---NULL-
8created_at作成日時DATETIME-×--CURRENT_TIMESTAMP-
9updated_at更新日時DATETIME-×--CURRENT_TIMESTAMPON UPDATE

ordersテーブル定義書

基本情報

テーブル名(物理)orders
テーブル名(論理)注文
説明注文情報を管理

カラム定義

No物理名論理名データ型桁数NULLPKFKデフォルト備考
1id注文IDBIGINT-×-AUTO自動採番
2user_idユーザーIDBIGINT-×--users.id
3order_number注文番号VARCHAR20×---'ORD-' + YYYYMMDD + 連番
4total_amount合計金額DECIMAL10,0×--0税込み
5statusステータスINT-×--1後述
6ordered_at注文日時DATETIME-×----
7shipped_at発送日時DATETIME---NULL-
8created_at作成日時DATETIME-×--CURRENT_TIMESTAMP-
9updated_at更新日時DATETIME-×--CURRENT_TIMESTAMP-

ステータス値

意味遷移元遷移先
1注文中-2, 9
2決済完了13, 9
3出荷準備中24, 9
4発送済み35
5配達完了4-
9キャンセル1, 2, 3-

制約

インデックス

usersテーブル

インデックス名カラム種別備考
PRIMARYid主キー-
uk_users_emailemailユニークメールアドレスの一意制約
idx_users_statusstatus通常ステータス検索用

ordersテーブル

インデックス名カラム種別備考
PRIMARYid主キー-
uk_orders_numberorder_numberユニーク注文番号の一意制約
idx_orders_useruser_id通常ユーザー検索用
idx_orders_statusstatus通常ステータス検索用
idx_orders_orderedordered_at通常日付検索用

外部キー

制約名カラム参照先ON DELETEON UPDATE
fk_orders_useruser_idusers(id)RESTRICTCASCADE

補足:テーブル定義書の実例では、どのカラムが主キー・外部キーなのか、インデックスがどこに張られているのかが記載されています。これらの制約は、データの一意性を保証し、テーブル間の関連を管理するために重要な役割を果たします。

読み方のポイント

1. 主キー(PK)を確認する

  • レコードを一意に識別するカラム
  • JOINの条件に使う
  • 通常はidという名前

2. 外部キー(FK)を確認する

  • 他テーブルとの関連
  • JOINの条件に使う
  • 参照整合性の制約

3. NULL可/不可を確認する

NULL意味実装への影響
×NULL不可必須入力、INSERT時に必須
NULL可省略可能、NULLチェック必要

4. デフォルト値を確認する

  • INSERT時に省略できるか
  • どんな値が入るか

5. インデックスを確認する

  • どのカラムに検索条件がつくか
  • ユニーク制約があるか

SQLを書くときの活用

SELECT文の例

-- usersテーブルから有効なユーザーを取得
SELECT id, email, name, phone
FROM users
WHERE status = 1
ORDER BY created_at DESC;

JOIN文の例

-- ordersとusersを結合
SELECT o.id, o.order_number, o.total_amount,
       u.name, u.email
FROM orders o
JOIN users u ON o.user_id = u.id
WHERE o.status = 2;

INSERT文の例

-- usersに新規レコード追加
INSERT INTO users (email, password_hash, name, phone)
VALUES ('user@example.com', 'hashed_password', '山田太郎', '03-1234-5678');
-- id, status, created_at, updated_at はデフォルト値が入る

よくある疑問

Q: 物理名と論理名の違いは?
  • 物理名:実際のDBで使う名前(英数字)
  • 論理名:人間が理解するための名前(日本語)
Q: ユニーク制約とは?

同じ値のレコードを入れられない制約。メールアドレスなど重複不可の項目に設定します。

Q: ON DELETE RESTRICT とは?

参照先のレコードを削除しようとしたとき、参照しているレコードがあるとエラーになる設定です。

設定動作
RESTRICT削除不可(エラー)
CASCADE一緒に削除
SET NULLNULLに更新

テーブル定義書でよくある落とし穴

落とし穴対策
カラム名を間違えるコピペで確実に
型の違いを見落とす型を確認してから実装
NULL可を見落とすNULLハンドリングを忘れない
桁数制限を見落とす桁数を確認して入力値をチェック

【実践】テーブル定義書からエンティティを作る

サンプルのusersテーブル定義書から、Javaのエンティティクラスを作成してみましょう。

ステップ1:基本構造を決める

テーブル基本情報を見て、クラスの基本構造を決めます。

import javax.persistence.*;
import java.time.LocalDateTime;

@Entity
@Table(name = "users")  // テーブル名(物理): users
public class User {
    // カラム定義をもとにフィールドを定義
}

ステップ2:主キーを設定する

カラム定義のPK列を見て、主キーを設定します。

// No.1: id - BIGINT, PK, AUTO
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

ステップ3:各カラムをフィールドにマッピングする

@Entity
@Table(name = "users")
public class User {

    // No.1: id - BIGINT, PK, AUTO
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    // No.2: email - VARCHAR(256), NOT NULL, ユニーク
    @Column(nullable = false, length = 256, unique = true)
    private String email;

    // No.3: password_hash - VARCHAR(256), NOT NULL
    @Column(name = "password_hash", nullable = false, length = 256)
    private String passwordHash;  // スネークケース→キャメルケース変換

    // No.4: name - VARCHAR(100), NOT NULL
    @Column(nullable = false, length = 100)
    private String name;

    // No.5: phone - VARCHAR(15), NULL許可
    @Column(length = 15)
    private String phone;  // nullableはデフォルトtrue

    // No.6: status - INT, NOT NULL, デフォルト1
    @Column(nullable = false)
    private Integer status = 1;  // デフォルト値を設定

    // No.7: last_login_at - DATETIME, NULL許可
    @Column(name = "last_login_at")
    private LocalDateTime lastLoginAt;

    // No.8: created_at - DATETIME, NOT NULL, デフォルトCURRENT_TIMESTAMP
    @Column(name = "created_at", nullable = false, updatable = false)
    private LocalDateTime createdAt;

    // No.9: updated_at - DATETIME, NOT NULL, ON UPDATE
    @Column(name = "updated_at", nullable = false)
    private LocalDateTime updatedAt;

    // ライフサイクルコールバック
    @PrePersist
    protected void onCreate() {
        createdAt = LocalDateTime.now();
        updatedAt = LocalDateTime.now();
    }

    @PreUpdate
    protected void onUpdate() {
        updatedAt = LocalDateTime.now();
    }

    // getter/setter は省略
}

カラム定義とアノテーションの対応表

カラム定義の項目JPAアノテーション
PK@Id + @GeneratedValue主キー
NOT NULL(×)@Column(nullable = false)必須カラム
NULL許可(○)@Column(nullableは省略可)任意カラム
桁数@Column(length = n)VARCHAR(256)
ユニーク制約@Column(unique = true)メールアドレスなど
物理名がJava命名規則と異なる@Column(name = "...")snake_case → camelCase
デフォルト値フィールド初期化= 1

外部キーがある場合

ordersテーブルのuser_id(FK)を例に、リレーションを設定します。

@Entity
@Table(name = "orders")
public class Order {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    // No.2: user_id - BIGINT, FK → users(id)
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id", nullable = false)
    private User user;

    @Column(name = "order_number", nullable = false, length = 20, unique = true)
    private String orderNumber;

    @Column(name = "total_amount", nullable = false)
    private BigDecimal totalAmount;

    @Column(nullable = false)
    private Integer status = 1;

    @Column(name = "ordered_at", nullable = false)
    private LocalDateTime orderedAt;

    @Column(name = "shipped_at")
    private LocalDateTime shippedAt;  // NULL許可

    // ... created_at, updated_at
}

ステータス値の対応

テーブル定義書にステータス値の一覧がある場合、Enum化すると便利です。

// ordersテーブルのステータス値をEnumに
public enum OrderStatus {
    ORDERING(1, "注文中"),
    PAID(2, "決済完了"),
    PREPARING(3, "出荷準備中"),
    SHIPPED(4, "発送済み"),
    DELIVERED(5, "配達完了"),
    CANCELLED(9, "キャンセル");

    private final int code;
    private final String label;

    OrderStatus(int code, String label) {
        this.code = code;
        this.label = label;
    }

    public int getCode() { return code; }
    public String getLabel() { return label; }

    public static OrderStatus fromCode(int code) {
        for (OrderStatus status : values()) {
            if (status.code == code) return status;
        }
        throw new IllegalArgumentException("Unknown code: " + code);
    }
}

テーブル定義書からエンティティを作るときのポイント

  1. 物理名と論理名:物理名(スネークケース)をDBに、論理名をコメントに
  2. NULL可否:NOT NULLのカラムにはnullable = falseを付ける
  3. 桁数:VARCHARの桁数はlengthで指定
  4. 外部キー@ManyToOne/@OneToManyで関連を表現
  5. デフォルト値:Javaのフィールド初期化で設定

関連ドキュメント