データ項目定義書とは
データ項目定義書は、システム全体で使用するコード値(区分値)・マスタデータの内容・初期投入データ・データ移行方針・データ量見積を定義した設計書です。テーブル定義書がテーブル構造を定義するのに対し、データ項目定義書は「何が入るか」を定義します。
① コード値・区分値の定義
システム内で使用するコード値(ステータスコード・区分値・フラグ値)を一覧で定義します。コード値の定義が設計書にない場合、実装担当者が独自判断でコードを決定してしまい、画面・バッチ・API間で不整合が生じます。
💡 コード値の管理方法
コード値の管理方法には「コードテーブル管理(DBテーブル)」と「定数管理(コード定義ファイル)」の2通りがあります。追加・変更が頻繁に起きるコードはコードテーブルで管理し、追加が稀で型安全に扱いたいコードは定数(Enumなど)で管理するのが一般的です。設計段階でどちらを採用するか方針を決定します。
| コード種別 | コード値 | 表示名 | 説明 | 管理方法 |
|---|---|---|---|---|
| 受注ステータス ( order_status) | 10 | 受注入力中 | 受注入力フォームで作業中の状態 | コードテーブル ( c_order_status) |
| 20 | 受注確定 | 受注承認済みで処理待ちの状態 | ||
| 30 | 出荷済み | 倉庫から出荷完了した状態 | ||
| 90 | キャンセル | 受注取り消し済みの状態 | ||
| 税区分 ( tax_type) | 10 | 標準税率(10%) | 一般的な商品に適用 | 定数 (Enum定義) |
| 8 | 軽減税率(8%) | 食料品・新聞等に適用 | ||
| 0 | 非課税 | 医療・教育等に適用 | ||
| 支払方法 ( payment_method) | 1 | クレジットカード | — | コードテーブル ( c_payment_method) |
| 2 | 銀行振込 | — |
② 初期マスタデータの定義
システム稼働開始時にDBに投入が必要な初期データ(種別マスタ・地域マスタ・設定マスタなど)を定義します。データ量が多い場合はCSVファイルとして管理します。
| テーブル名 | 初期データ件数 | データ取得方法 | 投入タイミング | 備考 |
|---|---|---|---|---|
| c_order_status(受注ステータス) | 4件 | 本設計書に全件記載 | 初回リリース時 | — |
| m_category(商品カテゴリ) | 約50件 | 業務担当者提供CSVから投入 | 初回リリース時 | 初期カテゴリ一覧は業務担当者が作成 |
| m_prefecture(都道府県) | 47件 | 本設計書にSQL添付 | 初回リリース時 | 変更なし・定常固定データ |
| m_user(初期ユーザー) | 約5件 | システム管理者が登録 | 初回リリース後・手動登録 | パスワードは初期値設定→初回ログイン時変更強制 |
③ データ移行方針の定義
既存システムからの移行対象データと移行方針を定義します。データ移行の範囲・変換ロジック・移行タイミングを基本設計段階で確定させます。
| 移行対象 | 現行テーブル | 新テーブル | 移行件数(概算) | 変換ロジック | 移行タイミング |
|---|---|---|---|---|---|
| 顧客マスタ | TBL_CUSTOMER | m_customer | 約1万件 | 文字コードShift-JIS→UTF-8変換。電話番号ハイフン統一化 | 本番移行日の前日夜間 |
| 商品マスタ | M_PRODUCT | m_product | 約3,000件 | 税区分コードの変換(旧コード→新コード) | 本番移行日の前日夜間 |
| 受注データ | TBL_ORDER | t_order / t_order_detail | 過去3年分(約30万件) | ヘッダ・明細の分割。旧ステータス→新ステータスコード変換 | 本番移行日の前日夜間 |
| 画像ファイル | ファイルサーバー /data/img | 新ファイルサーバー / S3 | 約5GB | ファイル名変換(商品コード変換に伴うリネーム) | 本番移行日の前日夜間 |
⚠️ 移行対象外データの明示も必要
「何を移行するか」だけでなく「何を移行しないか」も明示することが重要です。例:「5年以上前の受注データは移行対象外とし、必要な場合は旧システムで参照する」のような方針を明示することで、移行範囲の認識齟齬を防ぎます。
④ データ量見積(初期・最大・増加率)
DBの容量設計・パーティション設計・アーカイブ設計の根拠として、テーブル別のデータ量見積を行います。
| テーブル | 初期件数 | 年間増加率 | 5年後推定件数 | 推定サイズ(5年後) | 備考 |
|---|---|---|---|---|---|
| m_customer | 10,000件 | 10%/年 | 約16,100件 | 約3MB | — |
| m_product | 3,000件 | 5%/年 | 約3,800件 | 約2MB | — |
| t_order | 300,000件(移行分) | 100,000件/年 | 約800,000件 | 約400MB | 3年経過後にアーカイブ検討 |
| t_order_detail | 900,000件(移行分) | 300,000件/年 | 約2,400,000件 | 約1.2GB | t_orderに連動してアーカイブ |
| l_operation_log | 0件(新規) | 500,000件/年 | 約2,500,000件 | 約2GB | 1年経過後にパーティション設計 |
⑤ データ保持期間・アーカイブ方針
法令要件・業務要件に基づいてデータ保持期間とアーカイブ方針を定義します。
| テーブル | 保持期間 | 法令根拠(例) | アーカイブ方法 |
|---|---|---|---|
| t_order(受注データ) | 7年間 | 法人税法・消費税法(帳簿書類の保存義務) | 3年経過後に別テーブル(t_order_archive)へ移動 |
| l_operation_log(操作ログ) | 3年間 | 社内セキュリティポリシー | 1年経過後にCSV形式でファイルサーバーへ退避・DB削除 |
| m_customer(顧客データ) | 退会後3年 | 個人情報保護法(個人情報の利用目的の範囲) | 退会フラグ更新→3年後に匿名化処理 |
Python Tips — マスタCSVをバリデーションしてDB投入する
業務担当者から提供されるマスタデータCSVをバリデーションしてDB投入するスクリプトは、移行作業・初期データ投入で非常に有用です。
"""
業務担当者提供のマスタCSVをバリデーションしてPostgreSQLに投入するスクリプト。
pip install pandas psycopg2-binary
"""
import pandas as pd
import psycopg2
from psycopg2.extras import execute_values
from dataclasses import dataclass
from typing import Optional
import re
@dataclass
class ValidationError:
row: int
column: str
message: str
def validate_category_csv(df: pd.DataFrame) -> list[ValidationError]:
"""商品カテゴリCSVのバリデーション"""
errors = []
required_cols = ["category_code", "category_name", "parent_code", "sort_order"]
# 必須カラム存在チェック
for col in required_cols:
if col not in df.columns:
errors.append(ValidationError(0, col, f"必須カラム '{col}' が見つかりません"))
if errors:
return errors
for idx, row in df.iterrows():
row_num = idx + 2 # ヘッダー行を含めて人間が読む行番号
# category_code: 必須・英数字アンダースコアのみ
code = str(row.get("category_code", "")).strip()
if not code:
errors.append(ValidationError(row_num, "category_code", "カテゴリコードは必須です"))
elif not re.match(r'^[A-Za-z0-9_]+$', code):
errors.append(ValidationError(row_num, "category_code", "半角英数字とアンダースコアのみ使用可"))
# category_name: 必須・50文字以内
name = str(row.get("category_name", "")).strip()
if not name:
errors.append(ValidationError(row_num, "category_name", "カテゴリ名は必須です"))
elif len(name) > 50:
errors.append(ValidationError(row_num, "category_name", f"50文字以内(現在{len(name)}文字)"))
# sort_order: 数値
try:
int(row.get("sort_order", 0))
except (ValueError, TypeError):
errors.append(ValidationError(row_num, "sort_order", "表示順は整数で入力してください"))
# category_code の重複チェック
dup = df["category_code"].dropna().astype(str).str.strip()
dup_values = dup[dup.duplicated()].tolist()
if dup_values:
errors.append(ValidationError(0, "category_code", f"重複コードあり: {dup_values}"))
return errors
def insert_categories(conn, df: pd.DataFrame) -> int:
"""バリデーション済みのカテゴリCSVをDBに投入"""
records = [
(
str(row["category_code"]).strip(),
str(row["category_name"]).strip(),
str(row["parent_code"]).strip() if pd.notna(row["parent_code"]) else None,
int(row["sort_order"]),
)
for _, row in df.iterrows()
]
sql = """
INSERT INTO m_category (category_code, category_name, parent_code, sort_order)
VALUES %s
ON CONFLICT (category_code) DO UPDATE SET
category_name = EXCLUDED.category_name,
sort_order = EXCLUDED.sort_order;
"""
with conn.cursor() as cur:
execute_values(cur, sql, records)
conn.commit()
return len(records)
if __name__ == "__main__":
CSV_FILE = "category_master.csv"
DB_CONFIG = {"host":"localhost","port":5432,"dbname":"mydb","user":"myuser","password":"mypassword"}
df = pd.read_csv(CSV_FILE, encoding="utf-8-sig", dtype=str)
print(f"読込件数: {len(df)}件")
errors = validate_category_csv(df)
if errors:
print(f"\n❌ バリデーションエラー {len(errors)}件:")
for e in errors:
print(f" 行{e.row} [{e.column}] {e.message}")
else:
conn = psycopg2.connect(**DB_CONFIG)
count = insert_categories(conn, df)
conn.close()
print(f"\n✅ {count}件を投入しました")
定義チェックリスト
| チェック項目 | 確認ポイント |
|---|---|
| □ 全コード値・区分値が定義されているか | システム内で使用する全フラグ・ステータス・区分コードが一覧化されているか |
| □ コード値の管理方法が決定されているか | コードテーブル管理か定数管理かが決まっているか |
| □ 初期マスタデータが定義されているか | 初回リリース時に投入すべき全マスタデータが準備されているか |
| □ データ移行方針が定義されているか | 移行対象・変換ロジック・移行タイミング・移行対象外データが定義されているか |
| □ データ量見積が完了しているか | 初期件数・増加率・5年後推定件数・サイズ見積が全主要テーブルに定義されているか |
| □ データ保持期間・アーカイブ方針が定義されているか | 法令要件・業務要件に基づいた保持期間と削除/アーカイブ方法が定義されているか |