# ch05 — INSERT で 1 件追加する

Source: https://php-school.pages.dev/topics/db/ch05-insert/
Site: AIと学ぶPHPの学校 (https://php-school.pages.dev)
Lesson: データベース連携
Level: L4

Reference (official): https://www.php.net/manual/ja/book.pdo.php

## 本文

# ch05 — INSERT で 1 件追加する

## 概要

DB に新しい行を追加するのが **`INSERT INTO ... VALUES (...)`** 文。`INSERT INTO users (name, age) VALUES (?, ?)` のように「どのテーブルの・どの列に・何の値を入れるか」を書く。列名を明示する書き方を基本にする (テーブル設計が変わっても壊れにくい)。

値の渡し方は ch04 と同じ `prepare` + `execute`。INSERT でも文字列連結は厳禁で、ユーザー入力をそのまま `VALUES (...)` に埋めると SQL インジェクションの穴になる。

INSERT 特有のテーマが **採番された ID の取得**。`id INTEGER PRIMARY KEY AUTOINCREMENT` (SQLite) / `AUTO_INCREMENT` (MySQL) / `SERIAL` (PostgreSQL) のように **DB に自動採番させる** カラム設計が一般的で、その値は INSERT 直後に `$pdo->lastInsertId()` で取り出せる。「INSERT → ID 取得 → 関連テーブルにその ID で INSERT」という連鎖は頻出パターン。

## 学習目標

- `INSERT INTO ... VALUES (...)` で 1 件追加できる
- プレースホルダ (`?`) と `prepare/execute` で値を安全に渡せる
- `lastInsertId()` で自動採番された ID を取り出せる

## 所要時間

スライド 4 分 + ドリル 2 問 = **15 分**

## ドリル

| no | 内容 |
|---|---|
| 01 | 1 件 INSERT して、SELECT で全件確認 |
| 02 | 1 件 INSERT して、lastInsertId を出力 |

## スライド

---
marp: true
theme: dojo
paginate: true
size: 16:9
---

<!--
LLM_CONTEXT:
  Lesson 11 / Chapter 5
  目的: INSERT で 1 件追加し、lastInsertId で自動採番ID を取り出す
  扱わない: UPDATE / DELETE (ch06) / トランザクション (ch08) / SQL インジェクション対策の詳細 (ch09)
  読み上げ時間目安: 3 分半〜4 分
-->

# INSERT で 1 件追加する

Lesson 11 / Chapter 5

---

## SELECT は「読む」、INSERT は「書く」

```sql
INSERT INTO users (name, age) VALUES ('新人', 22);
```

- `INTO テーブル名 (列, 列)` で対象を指定
- `VALUES (値, 値)` で実際に入れる値を指定
- 1 文で 1 行追加される

---

## PHP からは `prepare` + `execute`

```php
<?php
$pdo = new PDO('sqlite:' . getenv('DOJO_DB_PATH'));
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$stmt = $pdo->prepare("INSERT INTO users (name, age) VALUES (?, ?)");
$stmt->execute(['新人', 22]);
```

- `?` は **プレースホルダ**。値の置き場所
- `execute([...])` で順番に値を当てはめる
- 値を SQL に直接埋め込まない → 安全 (ch09 で詳しく)

---

## 自動採番 ID は `lastInsertId()`

```php
<?php
$stmt = $pdo->prepare("INSERT INTO users (name, age) VALUES (?, ?)");
$stmt->execute(['新人', 22]);

$id = $pdo->lastInsertId();
echo "追加したIDは {$id}\n";
```

- `id` 列が `AUTOINCREMENT` のとき、INSERT 後に自動採番された値を取れる
- 直前の INSERT 1 件分の ID を返す

---

## 追加されたか確認は SELECT

```php
<?php
$stmt = $pdo->prepare("INSERT INTO users (name, age) VALUES (?, ?)");
$stmt->execute(['新人', 22]);

foreach ($pdo->query("SELECT id, name, age FROM users ORDER BY id") as $row) {
    echo "{$row['id']}: {$row['name']} ({$row['age']})\n";
}
```

- INSERT 自体は何も画面に出さない
- 「ちゃんと入ったか」を見るには SELECT で読む

---

## このチャプターでできるようになること

✅ `INSERT INTO ... VALUES (?, ?)` の形が書ける
✅ `prepare` + `execute([...])` でプレースホルダに値を渡せる
✅ `lastInsertId()` で自動採番された ID を取り出せる
✅ INSERT 後に SELECT で結果を確認できる

→ ドリルへ
