進め方の地図
| 週 | やること | 仕上がるもの |
|---|---|---|
| 1週目 | 授業1: なぜCSVでは足りないのか + 最初のテーブル | 最初のデータベースファイル |
| 2週目 | 授業2: SELECT ― 探す・並べる・集計する | SQL小問8本 |
| 3週目 | 授業3: 書き換える ― INSERT・UPDATE・DELETE | 安全な書き換え手順の型 |
| 4週目 | 授業4: テーブル設計 ― 分けてつなぐ | 2テーブル構成の設計図 |
| 5〜6週目 | 月末制作 | 在庫管理ミニデータベース |
授業1: なぜCSVでは足りないのか + 最初のテーブル
ユニット2のCSVは便利でした。でも、データが増えて・複数人で使うようになると、3つの壁に当たります ― ①検索が遅くなる ②同時に書き込むと壊れる ③「価格欄に文字」のような不正データを防げない。データベースは、この3つを最初から解決している保管庫です。
- つないで、表を定義する
db1.pyを作ります。
意味: 「itemsという表を作る。idは自動採番、nameは文字 (必須)、priceは整数 (必須)」。import sqlite3 con = sqlite3.connect("pan.db") cur = con.cursor() cur.execute(""" CREATE TABLE IF NOT EXISTS items ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, price INTEGER NOT NULL ) """)IF NOT EXISTSは「もうあれば作らない」の保険です。 - 1行しまう
cur.execute("INSERT INTO items (name, price) VALUES (?, ?)", ("メロンパン", 180)) con.commit()?は値の差し込み口 (プレースホルダ) です。値は必ず?で渡す ― 文字列の連結でSQLを組むと、悪意ある入力に乗っ取られる事故 (SQLインジェクション) の入り口になります。最初から正しい型で覚えましょう。 - 取り出す
実行するとfor row in cur.execute("SELECT * FROM items"): print(row) con.close()(1, 'メロンパン', 180)が返ります。idの1は、データベースが自動でつけた番号です。 - 2回実行してみるもう一度実行すると、メロンパンが2行になります (idは2)。「実行のたびに増えてよいのか?」― この違和感は正しいです。授業3で直します。
pan.db という1ファイルが、データベース本体です。コピーすればバックアップ、削除すれば全消去。SQLiteのこの手軽さが、学習にも小さな実務にも最適な理由です。授業2: SELECT ― 探す・並べる・集計する
SQLの花形はSELECTです。練習用に、パンの森の売上データをデータベースに引っ越しさせてから、質問攻めにします。
- 引っ越しスクリプトを書くユニット2の知識 (csv.DictReader) で読み、1行ずつINSERTします。
CSV→データベースの引っ越しは、実務でもよくある仕事そのものです。import csv, sqlite3 con = sqlite3.connect("pan.db") cur = con.cursor() cur.execute(""" CREATE TABLE IF NOT EXISTS sales ( id INTEGER PRIMARY KEY AUTOINCREMENT, day TEXT, item TEXT, price INTEGER, count INTEGER, total INTEGER ) """) with open("pan-uriage.csv", encoding="utf-8") as f: for row in csv.DictReader(f): cur.execute( "INSERT INTO sales (day, item, price, count, total) VALUES (?, ?, ?, ?, ?)", (row["日付"], row["商品名"], int(row["たんか"]), int(row["こすう"]), int(row["うりあげ"]))) con.commit() - 絞り込む (WHERE)
SELECT day, total FROM sales WHERE item = 'メロンパン'; - 並べる (ORDER BY)
「売上の大きい順に5件」。DESCが大きい順、LIMITが件数制限です。SELECT day, item, total FROM sales ORDER BY total DESC LIMIT 5; - 集計する (GROUP BY)
ユニット2で「数える辞書」で書いた商品別集計が、SQLなら1行です。手で書いた経験があるから、この1行の意味が読めるのです。SELECT item, SUM(total) FROM sales GROUP BY item;
お題: salesテーブルに、SQLで質問します。①食パンの行だけ全部 ②売上3000円以上の行 ③5月10日の売上合計 ④商品別の販売個数合計 ⑤日別売上のベスト3 ⑥一番安い商品の名前 ⑦「パン」を名前に含む商品の行 (LIKEを調べます) ⑧行数の合計 (COUNT)。
授業3: 書き換える ― INSERT・UPDATE・DELETE
書き換え系のSQLは強力で、強力なぶん危険です。プロの作法は1つ ― UPDATEとDELETEは、同じWHEREでSELECTしてから打つ。先に「どの行が対象になるか」を見るのです。
- 対象を先に見る
2行あることを確認します (授業1の手順4で増えた重複です)。SELECT * FROM items WHERE name = 'メロンパン'; - 重複を片づける (DELETE)
idを指定すれば1行だけ消せます。もしWHEREを忘れると全行消えます。怖さを知るために、消える前にDELETE FROM items WHERE id = 2;pan.dbをコピーしてバックアップを取り、練習用コピーの方でわざとDELETE FROM items;を体験しておきましょう。知識ではなく体験にしておくのが、事故防止の最強の薬です。 - 値上げする (UPDATE)
打つ前のSELECT → UPDATE → もう一度SELECTで確認、の3点セットを必ず守ります。UPDATEもWHEREを忘れると全行が書きかわります。UPDATE items SET price = 200 WHERE name = 'メロンパン'; - Pythonからも同じ
cur.execute("UPDATE items SET price = ? WHERE id = ?", (200, 1))のように、値は必ず?で渡します。書き換え後のcon.commit()を忘れると保存されません ― 「commitして初めて本当に書かれる」もここで体に入れます。
授業4: テーブル設計 ― 分けてつなぐ
データベース設計の核心は、たった1つの原則です ― 同じ情報を2か所に書かない。売上の表に商品の価格を毎回書いていると、値上げのとき100行直すことになります。商品の表と売上の表に分けて、idでつなぐのが正解です。
- 情報を全部書き出す在庫管理に必要な情報: 商品名・価格・入庫した数と日付・出庫した数と日付。
- 「もの」と「出来事」に分ける商品 (もの) は1回だけ登録するもの、入出庫 (出来事) は毎日増えるもの。性質が違うので表を分けます。
products: id, name, price moves: id, product_id, kind ('in'か'out'), count, day - つなぎ方を理解するmovesの
product_idに、productsのidを入れます。「メロンパンが3個入庫」は(product_id=1, kind='in', count=3)になります。名前ではなく番号でつなぐから、商品名を変えても履歴は壊れません。 - つないで読む (JOIN)
2つの表を貼り合わせて読むのがJOINです。まずこの1パターンだけ使えれば十分です。SELECT products.name, moves.kind, moves.count FROM moves JOIN products ON moves.product_id = products.id;
お題: 事業所の本棚の貸し出し管理を設計します。必要な情報: 本の題名・借りた人・借りた日・返した日。テーブル構成を紙に書き、CREATE TABLEまで実行します。
月末制作: 在庫管理ミニデータベース
授業4で設計した2テーブルを使って、メニュー式の在庫管理ツールを完成させます。パンの森の倉庫番になったつもりで作りましょう。
- メニュー: ①商品登録 ②入庫 ③出庫 ④在庫一覧 ⑤履歴表示 ⑥終了、の
while True:メニューを作ります (ユニット1の型です)。 - 在庫の計算: 在庫数は「入庫の合計 − 出庫の合計」で、moves表から計算します (SUMとGROUP BYの出番です)。在庫列を持たずに履歴から計算するのがポイント ― 数字の食い違いが起きません。
- 守りを入れる: 在庫以上の出庫を断る・数の入力にtry / except・登録のない商品番号を断る、の3つの防御を入れます。
- 検査と納品: 意地悪な操作10連発に耐えたら、スタッフに倉庫番ごっこ (登録 → 入庫 → 出庫 → 一覧) をしてもらい、GitHubにpushして完了です。
つまずきやすいポイント
con.commit() 忘れです。書き換え (INSERT / UPDATE / DELETE) のあとは必ずcommit。読み (SELECT) には不要です。発展チャレンジ (余力のある方へ)
- 「DB Browser for SQLite」という無料ソフトを入れると、pan.dbの中身を表計算ソフトのような画面で眺められます。自分のSQLの結果を目で確かめる検算機になります。
- 在庫ツールに「在庫が3個以下の商品を警告表示する」機能を足してみましょう (HAVINGという仲間を調べることになります)。
- 「インデックス」とは何か、なぜ検索が速くなるのかを調べて、3行で説明メモを書いてみましょう。データ量が増えたときの切り札です。