📖 テーマ設定
🔊 音声設定
1.2
1.0
1.0
▶️ 再生コントロール
🎵 BGM設定
0.3
🔔 効果音設定
0.3

テーブル作成演習(社員研修管理を例に)

概要

  • 日程: Day 2 / セッション 10
  • 時間: 15:10-15:40
  • 形式: 実習
  • ゴール: 「研修コース」「受講履歴」テーブルを、制約付きで自分で設計・CREATE TABLEし、サンプルデータを挿入できる
  • 学習形式: ハンズオン実習(AIペアプログラミング)

導入(5分)

座学で学んだ CREATE TABLE と制約を、ここからは実際に手を動かして使います。題材は「社員研修管理」。会社で社員がいろいろな研修コースを受講する状況を、テーブルで表現してみましょう。

これは、いわば建築の図面引きです。座学では材料(制約・データ型)を見てきました。ここでは実際に図面(CREATE TABLE文)を書いて、家(テーブル)を建てます。

ターミナルで psql に接続して始めましょう。

docker exec -it postgres-sandbox psql -U postgres -d sandbox

実習・演習(20分)

課題1: courses テーブルを設計・作成

「研修コース」テーブルを作ります。次の要件を満たすように CREATE TABLE を書いてください。

要件

  • course_id:主キー、自動採番
  • course_name:必須、最大100文字
  • duration_hours:必須、整数、0より大きい
  • category:任意、最大50文字
  • created_at:作成日時、デフォルトで現在時刻

ヒント

  • 主キーは SERIAL PRIMARY KEY
  • 「0より大きい」は CHECK (duration_hours > 0)
  • 「現在時刻」は DEFAULT CURRENT_TIMESTAMP

解答例

CREATE TABLE courses (
    course_id SERIAL PRIMARY KEY,
    course_name VARCHAR(100) NOT NULL,
    duration_hours INTEGER NOT NULL CHECK (duration_hours > 0),
    category VARCHAR(50),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

作成後 \d courses でテーブル定義を確認しましょう。制約がきちんと付いていれば成功です。

課題2: enrollments テーブルを設計・作成

「受講履歴」テーブルを作ります。社員がどのコースをいつ受けたかを記録します。

要件

  • enrollment_id:主キー、自動採番
  • employee_id:必須、employees テーブルへの外部キー
  • course_id:必須、courses テーブルへの外部キー
  • enrolled_at:必須、申込日時、デフォルトで現在時刻
  • completed_at:完了日時、未完了ならNULL
  • score:得点、0〜100の範囲、未採点ならNULL

ヒント

  • 外部キーは INTEGER REFERENCES 親テーブル(主キー列) の形
  • 「0〜100の範囲」は CHECK (score BETWEEN 0 AND 100)

解答例

CREATE TABLE enrollments (
    enrollment_id SERIAL PRIMARY KEY,
    employee_id INTEGER NOT NULL REFERENCES employees(employee_id),
    course_id INTEGER NOT NULL REFERENCES courses(course_id),
    enrolled_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    completed_at TIMESTAMP,
    score INTEGER CHECK (score BETWEEN 0 AND 100)
);

\d enrollments で「Foreign-key constraints」の欄を見て、employeescourses への参照が表示されていれば成功です。

課題3: サンプルデータを入れる

作ったテーブルにデータを入れて、SELECTで確認しましょう。

コース3件

INSERT INTO courses (course_name, duration_hours, category) VALUES
('SQL基礎', 14, 'データベース'),
('ビジネスマナー', 6, 'マナー'),
('プログラミング入門', 21, '開発');

受講履歴3件

existing の社員ID 1, 2, 3 と、上で作ったコースを組み合わせます。

INSERT INTO enrollments (employee_id, course_id, completed_at, score) VALUES
(1, 1, '2024-04-15 17:00:00', 85),
(2, 1, '2024-04-15 17:00:00', 92),
(3, 2, NULL, NULL);

3件目は「申込みしたけどまだ完了していない」というデータです。completed_atscore がNULLでも、CHECK制約に引っかからないことに注目してください。

確認SELECT

SELECT
    e.last_name || ' ' || e.first_name AS employee_name,
    c.course_name,
    en.enrolled_at,
    en.completed_at,
    en.score
FROM enrollments en
JOIN employees e ON en.employee_id = e.employee_id
JOIN courses c ON en.course_id = c.course_id
ORDER BY en.enrolled_at DESC;

3件出ますか?社員名・コース名・得点が並んで見えれば完璧です。

課題4(チャレンジ): 制約の動作確認

制約は「ちゃんと弾いてくれる」ことを確認すると安心できます。次のINSERTを試してください。わざとエラーになる例です

-- 1) 存在しない部署IDで社員を登録(失敗するはず)
INSERT INTO enrollments (employee_id, course_id) VALUES (9999, 1);

-- 2) 得点が範囲外(失敗するはず)
INSERT INTO enrollments (employee_id, course_id, score) VALUES (1, 1, 150);

-- 3) 受講時間が0以下(失敗するはず)
INSERT INTO courses (course_name, duration_hours) VALUES ('テスト', 0);

それぞれどんなエラーメッセージが出るか、AIに「このエラーは何を意味するか」を聞いてみましょう。

成果物

  • courses enrollments の CREATE TABLE 文
  • それぞれにINSERTしたサンプルデータ
  • JOINで「誰がどのコースを受けたか」を表示できたSELECT結果
  • 制約が機能してエラーが出たことの確認メモ

まとめ(5分)

CREATE TABLEで「列名・型・制約」を書き、INSERTで「データを入れる」、SELECTで「確認する」。この3工程をひと続きで体験できたら、もうテーブル設計者の入り口に立っています。

制約はうるさく感じるかもしれませんが、運用に乗せたときに「変なデータが入る前に止まってくれる」最強の味方です。設計時の数行が、未来の数百件のトラブルを防いでくれます。

🔄 振り返りチェック

  • 自分で書いた CREATE TABLE 文を、明日見ても理解できますか?
  • 外部キーが「向こうの主キーに存在する値だけ入れさせない」働きを実感しましたか?
  • CHECK制約がどんなときに役立つか、自分の例を1つ言えますか?

補足資料

  • 発展課題: 作った enrollments テーブルに、「同じ社員が同じコースに2回申し込めない」制約を追加するにはどうすればよいか考えてみる(ヒント: 複合UNIQUE)

学習ガイド

想定される質問と回答例

質問 ヒント
テーブル名は単数 course ?複数 courses チームのルール次第。世間では「複数形」が主流(テーブル=行の集まり、と考えると複数形が自然)
一度作ったテーブルの列を増やしたい ALTER TABLE courses ADD COLUMN description TEXT; のように後から追加可能
間違って作ったテーブルを消したい DROP TABLE テーブル名; で削除。本番では絶対に確認してから
外部キーの参照先テーブルが先に必要? はい。CREATE順は「親→子」、DROP順は「子→親」(依存関係の方向に注意)

つまずきやすいポイント

つまずきポイント ヒント
relation "xxx" does not exist エラー テーブル名のタイポ、または作っていないテーブルを参照している
violates foreign key constraint エラー 親テーブルに該当する値がない。SELECT で確認してから子にINSERT
制約を後で名前付きで識別したい CONSTRAINT chk_score CHECK (score BETWEEN 0 AND 100) のように名前を付けると、エラー時に分かりやすい
読み上げを開始します...

AIに質問する