第1部:アプリケーション設計 Step 4 / 24

データベース設計

データベース設計はアプリの土台。適切なテーブル構造とリレーションを設計することで、効率的なデータ管理ができます。

データベース設計の基本概念

テーブル(Table)

データを格納する表。行(レコード)と列(カラム)で構成。

users テーブル

idnameemail
1山田yamada@...

リレーション(Relation)

テーブル間の関連。外部キー(FK)で参照。

posts.author_id -> users.id

「記事は1人のユーザーに属する」

主なリレーションの種類

1対多(One-to-Many)

1人のユーザーが複数の記事を持つ

User(1) -> Post(多)

多対多(Many-to-Many)

記事は複数のタグを持ち、タグは複数の記事に付く

Post(多) <-> Tag(多) 中間テーブルが必要

1対1(One-to-One)

ユーザーは1つのプロフィールを持つ

User(1) <-> Profile(1)

ブログアプリのテーブル設計

ER図(エンティティ関連図)

users

id, email, name, password

-> 1:N ->

posts

id, title, content, author_id

users テーブル

カラム名 制約 説明
id INT PK, AUTO_INCREMENT 主キー
email VARCHAR(255) UNIQUE, NOT NULL メールアドレス
name VARCHAR(100) NOT NULL 表示名
password_hash VARCHAR(255) NOT NULL ハッシュ化パスワード
created_at DATETIME DEFAULT NOW() 作成日時
updated_at DATETIME ON UPDATE NOW() 更新日時

posts テーブル

カラム名 制約 説明
id INT PK, AUTO_INCREMENT 主キー
title VARCHAR(255) NOT NULL 記事タイトル
content TEXT NOT NULL 記事本文
author_id INT FK -> users.id 著者ID
created_at DATETIME DEFAULT NOW() 作成日時
updated_at DATETIME ON UPDATE NOW() 更新日時

MySQL でのテーブル作成

-- usersテーブル
CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    email VARCHAR(255) NOT NULL UNIQUE,
    name VARCHAR(100) NOT NULL,
    password_hash VARCHAR(255) NOT NULL,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

-- postsテーブル
CREATE TABLE posts (
    id INT AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(255) NOT NULL,
    content TEXT NOT NULL,
    author_id INT NOT NULL,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE CASCADE
);

-- インデックス(検索高速化)
CREATE INDEX idx_posts_author_id ON posts(author_id);
CREATE INDEX idx_posts_created_at ON posts(created_at DESC);

SQLAlchemy モデル(Python)

from sqlalchemy import Column, Integer, String, Text, DateTime, ForeignKey
from sqlalchemy.orm import relationship
from sqlalchemy.sql import func
from database import Base

class User(Base):
    __tablename__ = "users"

    id = Column(Integer, primary_key=True, index=True)
    email = Column(String(255), unique=True, nullable=False, index=True)
    name = Column(String(100), nullable=False)
    password_hash = Column(String(255), nullable=False)
    created_at = Column(DateTime, server_default=func.now())
    updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now())

    # リレーション
    posts = relationship("Post", back_populates="author")


class Post(Base):
    __tablename__ = "posts"

    id = Column(Integer, primary_key=True, index=True)
    title = Column(String(255), nullable=False)
    content = Column(Text, nullable=False)
    author_id = Column(Integer, ForeignKey("users.id"), nullable=False)
    created_at = Column(DateTime, server_default=func.now())
    updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now())

    # リレーション
    author = relationship("User", back_populates="posts")

ポイント:SQLAlchemyのrelationshipを使うと、post.authorのようにオブジェクト経由でリレーション先にアクセスできます。

設計のコツ

良い設計

  • 適切な正規化(データの重複を避ける)
  • 明確な命名(users, posts)
  • created_at, updated_atを必ず含める
  • 適切なインデックス設定

避けるべきこと

  • JSONカラムの多用
  • パスワードを平文で保存
  • 曖昧な命名(data, info)
  • 外部キー制約なしの参照

まとめ

  • テーブル間のリレーション(1対多、多対多)を理解する
  • 適切な型と制約(NOT NULL, UNIQUE, FK)を設定
  • created_at, updated_atは必須
  • パスワードは必ずハッシュ化して保存
API設計 次へ:Dockerとは