はじめに ── この学習室の使い方
ここは、「データベース? SQL? なにそれおいしいの?」という人のための学習室です。プログラミング経験も専門知識もいりません。例え話の舞台は冒険者ギルド。受付嬢になったつもりで、名簿やクエスト台帳を管理しながらデータベースの世界を旅していきます。
使い方はかんたん。上の「教本」で章を読む → 章末のボタンで「道場」へ行き、その章の依頼(練習問題)を解く。この繰り返しです。道場では本物のSQLiteがブラウザの中で動いているので、読んだそばから実際にSQLを打てます。スマホでもPCでもOKです。
【ヒント】暗記しなくていい
ここに出てくる命令文は、ぜんぶ「あとで見返せばいい」ものです。プロでも細かい書き方は毎回調べています。大事なのは「データベースにこういうことをさせられる」と知っておくことだけ。付録Cのチートシートをいつでも開けます。
じっくり紙で読みたい人・印刷したい人のために、この教本のPDF版も用意してあります。
PDF版をダウンロード(全21ページ・印刷用)
第1章 データベースってなに?
一言でいうと「めちゃくちゃ整理上手な倉庫番」
データベース(DB)とは、大量のデータをきちんと整理してしまっておいて、必要なときにサッと取り出せるようにする仕組みのことです。
冒険者ギルドを想像してください。何百人もの冒険者が登録していて、毎日クエストの受注や報告がやってきます。もし名簿が「紙の山に適当に積んである」状態だったら、「Bランク以上で今ヒマな冒険者を呼んで!」と言われた受付嬢は、紙の山を一枚ずつめくるハメになります。日が暮れます。
そこで、名簿を帳簿にまとめ、五十音順の索引をつけ、ランク別の付箋を貼っておく。こうすれば一瞬で探せます。この「整理された帳簿と超優秀な倉庫番」をコンピュータで実現したものがデータベースです。
Excelとなにが違うの?
「表で管理するならExcelでよくない?」と思いますよね。少ないデータならExcelで十分です。ただしデータベースには、Excelが苦手なことをこなす力があります。
- 量に強い:何百万行でも一瞬で探せます。Excelは数十万行あたりから固まりがち。
- 同時に使える:100人が同時に読み書きしても壊れません。
- ルールを守らせる:「この欄は空欄禁止」「同じ会員番号は登録禁止」を機械的に守らせられます。
- 壊れにくい:書き込み途中で停電しても中途半端にならない仕組みがあります。
実は毎日お世話になっている
通販サイトの商品一覧・購入履歴、スマホゲームの所持キャラやガチャ履歴、銀行の残高、小説投稿サイトの作品・ブックマーク・感想欄……身の回りのほとんどのサービスの裏で、データベースが動いています。
【ヒント】DBMSという言葉
厳密には、データの集まりを「データベース」、それを管理するソフトを「DBMS」と呼び分けます。有名どころは MySQL、PostgreSQL、SQLite、Oracle など。日常会話では全部ひっくるめて「データベース」でOK。この道場で動いているのはSQLiteです。
第2章 テーブル 〜 データの入れ物
テーブル=1冊の帳簿
データベースの中では、データはテーブルという表の形でしまわれています。まずは、この学習室でずっと使う「冒険者テーブル」を見てください。
| id | name(名前) | rank | job(職業) | gold(所持金) |
|---|
| 1 | アルト | B | 剣士 | 3200 |
| 2 | ベル | A | 魔法使い | 8100 |
| 3 | カイ | C | 斥候 | 950 |
| 4 | ドロテア | S | 聖職者 | 15000 |
| 5 | エッジ | C | 剣士 | 1200 |
テーブル「adventurers(冒険者)」── 本書の主役たち
行と列 〜 たった2つの用語だけ覚えよう
- 行(ロウ/レコード):横の1行。「アルト、Bランク、剣士、3200ゴールド」のように1人分・1件分のデータのかたまり。
- 列(カラム):縦の1列。「name」「rank」のような項目名・記入欄の見出し。
「テーブルは帳簿、行は1件分の記入、列は記入欄の見出し」。これだけです。データベースの中には、目的別のテーブルが何冊も入っています。
主キー 〜 絶対にかぶらない背番号
左端の「id」列は主キーと呼ばれる背番号です。「アルト」が2人入会しても、idが違えば絶対に取り違えません。「主キーは行を1つに特定できる、重複しない値」とだけ覚えてください。第9章で大活躍します。
【ヒント】列名が英語なのはなぜ?
慣習として半角英語でつけるとトラブルが少ないからです。意味はそのつど日本語で添えるので安心してください。
第3章 SQLってなに?
SQL=データベース係への指示書
データをしまったり取り出したりするとき、私たちはデータベースにSQL(エスキューエル)という言葉で命令を出します。「データベース専用の超シンプルな英語」だと思ってください。たとえば「冒険者テーブルの中身を全部見せて」は──
SELECT * FROM adventurers;
「adventurersテーブルから(FROM)、全部の列(*)を、取り出して見せて(SELECT)」
英語の語順どおり「SELECT(選べ)… FROM(〜から)…」と読み下せます。文末のセミコロン( ; )は日本語の「。」にあたります。
【ヒント】大文字と小文字
select と書いても動きますが、命令の単語を大文字、テーブル名・列名を小文字にすると読みやすいので、本書はそのスタイルで統一します。
SQLは大きく分けて2種類
- 読む系:SELECT。何回実行してもデータは変わらない、安全な命令。
- 書く系:INSERT(追加)、UPDATE(書きかえ)、DELETE(削除)、CREATE(作成)など。データが実際に変わる命令。
まず安全な「読む系」をたっぷり練習してから(第4〜6章)、「書く系」へ進みます(第7章・第10章)。
練習環境について
紙の本では練習環境の準備が一仕事ですが、この学習室では「道場」タブを開くだけ。冒険者テーブルもクエスト台帳もすでに用意されています。将来、自分のPCに本格的な環境(DB Browser for SQLite、MySQLなど)を作るときも、ここで覚えたSQLはそのまま通用します。
第4章 SELECT 〜 データを見る
全部見る:SELECT *
SELECT * FROM adventurers;
*(アスタリスク)は「全部の列」の記号。
「とりあえず中身を見たい」ときの定番です。
列をしぼって見る
名前とランクだけ見たいなら、* の代わりに列名をカンマ区切りで並べます。
SELECT name, rank FROM adventurers;
| name | rank |
|---|
| アルト | B |
| ベル | A |
| カイ | C |
| ドロテア | S |
| エッジ | C |
実行結果:指定した2列だけが表示される
ポイントは、元のテーブルは一切変わっていないこと。SELECTは「帳簿から必要な部分を書き写して見せてもらう」だけの操作なので、いくら実行しても安全です。
ちょっとした計算もできる
SELECT name, gold + 500 FROM adventurers;
全員の所持金に報酬500を足したら?を「見る」だけ。実際の所持金は変わらない。
【ヒント】読み下しのコツ
SELECT文は「FROMから読む」と意味がとりやすい。「FROM adventurers(冒険者テーブルから)→ SELECT name, rank(名前とランクを見せて)」。
第5章 WHERE 〜 条件で絞り込む
基本形:WHERE 条件
「剣士だけ見せて」は、うしろに WHERE(〜のところの)をつけます。
SELECT * FROM adventurers
WHERE job = '剣士';
文字は '(シングルクォート)で囲む。数字は囲まない。
| id | name | rank | job | gold |
|---|
| 1 | アルト | B | 剣士 | 3200 |
| 5 | エッジ | C | 剣士 | 1200 |
実行結果:jobが「剣士」の行だけが残る
比較の記号いろいろ
| 記号 | 意味 | 例 |
|---|
| = | 等しい | rank = 'A' |
| <> (または !=) | 等しくない | job <> '剣士' |
| > | より大きい | gold > 3000 |
| >= | 以上 | gold >= 3000 |
| < | より小さい | gold < 1000 |
| <= | 以下 | gold <= 1000 |
条件を組み合わせる:AND と OR
- AND=かつ。両方満たす行だけ。
- OR=または。どちらかでOK。
SELECT * FROM adventurers
WHERE job = '剣士' AND gold >= 3000;
SELECT * FROM adventurers
WHERE rank = 'S' OR rank = 'A';
あいまい検索:LIKE
SELECT * FROM adventurers
WHERE name LIKE '%ル%';
%は「0文字以上のなにか」。'%ル%'=ルを含む。'ア%'=アで始まる。'%ト'=トで終わる。
【ヒント】=とLIKEの使い分け
完全一致なら =、一部だけわかっているなら LIKE。検索窓の裏側ではたいていLIKEが働いています。
第6章 ORDER BY と LIMIT
並べ替える:ORDER BY
SELECT * FROM adventurers
ORDER BY gold DESC;
多い順(DESC=降順)。少ない順は ASC(昇順)。無指定なら昇順。
件数をしぼる:LIMIT
SELECT name, gold FROM adventurers
ORDER BY gold DESC
LIMIT 3;
上位3件だけ。「所持金トップ3」の完成。
WEBの「人気ランキングTOP10」や「新着5件」は、この ORDER BY + LIMIT で作られています。
書く順番のルール
SELECT 列名 -- 何を見るか
FROM テーブル名 -- どの帳簿から
WHERE 条件 -- どの行を(省略可)
ORDER BY 列名 -- どう並べて(省略可)
LIMIT 件数 -- 何件だけ(省略可)
「セレクト・フロム・ウェア・オーダーバイ・リミット」と呪文のように。-- から行末はメモ書き(コメント)。
【ヒント】迷ったらこの型に当てはめる
SQLの9割はこの型の穴埋めです。「何を・どこから・どの条件で・どう並べて・何件」。日本語でこの5つを言えれば、もう書けたも同然。
第7章 INSERT / UPDATE / DELETE
追加する:INSERT
新人「フィオ」が入会してきました。行を1行追加します。
INSERT INTO adventurers (id, name, rank, job, gold)
VALUES (6, 'フィオ', 'C', '弓使い', 500);
「adventurersに差し込め。(列の並び)の順で値は(…)だ」。列と値の並びは対応させる。
書きかえる:UPDATE
UPDATE adventurers
SET rank = 'A'
WHERE id = 1;
「adventurersを更新。rankを'A'にセット。ただしidが1の行だけ」。
【注意!】WHEREを忘れると全滅する
UPDATE文からWHEREを消すと全員のランクがAになります。DELETEでWHEREを忘れると全行消えます。初心者からベテランまで全員が一度はやらかす、SQL界いちばん有名な事故。実行前に指差し確認──「WHERE、ある?」
削除する:DELETE
DELETE FROM adventurers
WHERE id = 5;
「adventurersから消せ。idが5の行を」。
事故を防ぐ安全確認テクニック
- 先にSELECTで狙いを確認:同じWHEREでSELECTし、狙いの行だけ出るか目視してから書きかえる。
- 主キー(id)で指定:名前指定は同姓同名を巻き込む恐れ。idなら1行を確実に狙える。
- 練習用データで試す:本番データでいきなり試さない。鉄則。道場ならいくら壊しても初期化できます。
-- 手順1: まず狙いを確認
SELECT * FROM adventurers WHERE id = 5;
-- 手順2: 狙いどおりなら DELETE に書きかえて実行
DELETE FROM adventurers WHERE id = 5;
プロも実際にやっている安全手順。
第8章 集計
集計の関数たち
| 関数 | 意味 | 例 |
|---|
| COUNT(*) | 行数を数える | 冒険者は何人? |
| SUM(列) | 合計 | 全員の所持金合計は? |
| AVG(列) | 平均 | 所持金の平均は? |
| MAX(列) | 最大値 | いちばんの金持ちは? |
| MIN(列) | 最小値 | いちばんの金欠は? |
SELECT COUNT(*) FROM adventurers; -- 人数
SELECT AVG(gold) FROM adventurers; -- 平均所持金
グループ分けして集計:GROUP BY
「職業ごとに何人?」は、GROUP BY で同じ値の行をひとまとめにして、まとまりごとに集計します。
SELECT job, COUNT(*)
FROM adventurers
GROUP BY job;
「jobが同じ行どうしで班をつくり、班ごとに人数を数えよ」。
イメージは「トランプを数字ごとの山に分けてから、山ごとに枚数を数える」。GROUP BYが山分けの基準、COUNTやSUMが山ごとの計算、という役割分担です。
集計した結果で絞り込む:HAVING
SELECT job, COUNT(*)
FROM adventurers
GROUP BY job
HAVING COUNT(*) >= 2;
「班分け後、2人以上の班だけ表示」。
【ヒント】WHEREとHAVINGの見分け方
1行だけ見て判定できる条件はWHERE(goldが1000以上の人)。班にまとめないと判定できない条件はHAVING(2人以上いる職業)。自問しよう──「この条件、1人だけ見て判定できる?」
第9章 JOIN 〜 テーブルをつなぐ
なぜテーブルを分けるのか
ギルドにはクエストの受注台帳もあります。1枚の表に「冒険者+クエスト」を全部書くと、アルトが3件受注したら職業や所持金を3回書くハメに。ムダな上、昇格したら3か所直す必要があり、直し漏れが起きます。
そこで、冒険者の情報は名簿に1回だけ書き、台帳には背番号(id)だけをメモする。これがデータベース流の整理術です。
| quest_id | quest_name | reward | adventurer_id(受注者の背番号) |
|---|
| 101 | 薬草採取 | 300 | 3 |
| 102 | ゴブリン退治 | 1500 | 1 |
| 103 | 遺跡の調査 | 5000 | 2 |
| 104 | 迷子の猫さがし | 200 | 1 |
テーブル「quests(クエスト台帳)」── 受注者は背番号でメモしてある
背番号をたどって表を合体:JOIN
でも台帳だけ見ても「idが1って誰!?」となります。そこでJOIN。背番号を手がかりに2つの表をつなげ、1枚の表として見る命令です。
SELECT quests.quest_name, adventurers.name, quests.reward
FROM quests
JOIN adventurers
ON quests.adventurer_id = adventurers.id;
「questsとadventurersをつなげ。つなぎ目(ON)は台帳のadventurer_idと名簿のidが等しいところ」。「テーブル名.列名」は「どっちの表の列か」の指定。
| quest_name | name | reward |
|---|
| 薬草採取 | カイ | 300 |
| ゴブリン退治 | アルト | 1500 |
| 遺跡の調査 | ベル | 5000 |
| 迷子の猫さがし | アルト | 200 |
実行結果:背番号が名前に置きかわり、人間に読める台帳になった
しくみは、各行の背番号を名簿と照合する作業(id 3→カイだ!)を、全行ぶん一瞬でこなしているだけです。
外部キーという言葉
questsのadventurer_idのように、よそのテーブルの主キーを指す列を外部キーと呼びます。主キー(本人の背番号)と外部キー(その番号のメモ)が、テーブル同士をつなぐ糸です。
【ヒント】JOINまで来たあなたへ
SELECT・WHERE・GROUP BY・JOIN。この4つで実務のSQLの大半は読めます。求人票の「SQLが使える方」もおおむねこのレベル。ようこそ、データベースが使える側の世界へ。
第10章 CREATE TABLE 〜 テーブルを作る
テーブル作成の基本形
CREATE TABLE adventurers (
id INTEGER PRIMARY KEY, -- 整数。主キー
name TEXT NOT NULL, -- 文字。空欄禁止
rank TEXT,
job TEXT,
gold INTEGER
);
「adventurersという表を作れ。列と型とルールは…」
型 〜 その欄に入れていい値の種類
| 型(SQLite流) | 入るもの | 例 |
|---|
| INTEGER | 整数 | 3200、-5 |
| REAL | 小数 | 3.14 |
| TEXT | 文字 | 'アルト' |
| BLOB | 画像などのデータそのもの | (あまり使わない) |
MySQLなどでは INT、VARCHAR、DATE など名前が少し違いますが、「種類を宣言する」考え方は共通です。
ルール(制約)をつける
- PRIMARY KEY:主キー。重複禁止&空欄禁止の背番号。
- NOT NULL:空欄禁止。「名前は必ず書いてね」。
- UNIQUE:重複禁止。「同じメールアドレスは登録できません」の正体。
道場の「自由練習の間」で、自分のテーブル(蔵書、ゲームの記録、推しの一覧…)をぜひ作ってみてください。作って壊して初期化して、が最高の練習です。
付録A よくあるエラーと対処法
| エラーの例 | 意味 | よくある原因と直し方 |
|---|
| syntax error | 文法まちがい | スペルミス(SELCT→SELECT)、カンマの過不足、クォートの閉じ忘れ。 |
| no such table | そんな表は無い | テーブル名の打ちまちがい。単数/複数(adventurer/adventurers)に注意。 |
| no such column | そんな列は無い | 列名の打ちまちがい。SELECT * で正しい列名を確認。 |
| UNIQUE constraint failed | 重複禁止ルール違反 | すでにあるidでINSERTした。別の番号に。 |
| NOT NULL constraint failed | 空欄禁止ルール違反 | 必須の列に値がない。VALUESと列の対応を見直す。 |
エラー文は英語ですが、パターンは驚くほど少ないです。「エラー文をそのままコピーして検索」が世界共通の解決法で、プロも毎日やっています。
【ヒント】エラーが出ても壊れない
文法エラーならSQLは実行されず、データは1ミリも変わっていません。練習中はわざと間違えて、エラー文と仲良くなっておきましょう。
付録B 用語集
- データベース(DB)
- 大量のデータを整理して保管し、素早く出し入れできる仕組み。整理上手な倉庫番。
- DBMS
- データベースを管理するソフト本体。MySQL、PostgreSQL、SQLite、Oracleなど。
- SQL
- データベースへの命令に使う言葉。「エスキューエル」と読む人が多い。
- テーブル
- データベース内の1つの表。帳簿1冊。
- 行(ロウ/レコード)
- 表の横1行。1件分のデータ。
- 列(カラム)
- 表の縦1列。データの項目・記入欄。
- 主キー
- 行を1つに特定できる、重複しない背番号の列。
- 外部キー
- よそのテーブルの主キーを指し示す列。テーブルをつなぐメモ。
- NULL(ヌル)
- 値が入っていない状態の印。0でも空文字でもない「未記入」。
- クエリ
- データベースへの問い合わせ文。SQL文とほぼ同義。
- 型
- 列に入れられる値の種類の宣言。整数、文字など。
- 制約
- 列に課すルール。NOT NULL、UNIQUEなど。
- トランザクション
- 複数の書き込みを「全部成功か全部なし」の二択で扱う仕組み。卒業後に学ぼう。
- インデックス
- 検索を速くする索引。本の巻末索引と同じ発想。これも卒業後の楽しみ。
付録C SQLチートシート
-- 見る ---------------------------------------------
SELECT * FROM テーブル; -- 全部見る
SELECT 列1, 列2 FROM テーブル; -- 列をしぼる
SELECT * FROM テーブル WHERE 条件; -- 行をしぼる
SELECT * FROM テーブル ORDER BY 列 DESC; -- 多い順
SELECT * FROM テーブル LIMIT 10; -- 10件だけ
-- 条件の書き方 ---------------------------------------
列 = 値 / 列 <> 値 / 列 >= 値 / 列 <= 値
条件 AND 条件 / 条件 OR 条件
列 LIKE '%文字%' -- 部分一致
-- 集計 ----------------------------------------------
SELECT COUNT(*) FROM テーブル; -- 何件?
SELECT 列, COUNT(*) FROM テーブル
GROUP BY 列; -- グループごと
GROUP BY 列 HAVING COUNT(*) >= 2; -- 集計後の絞り込み
-- つなぐ ---------------------------------------------
SELECT * FROM 表A
JOIN 表B ON 表A.外部キー = 表B.主キー;
-- 書く(実行前に WHERE、ある? と指差し確認!)-----
INSERT INTO テーブル (列, ...) VALUES (値, ...);
UPDATE テーブル SET 列 = 値 WHERE 条件;
DELETE FROM テーブル WHERE 条件;
-- 作る ----------------------------------------------
CREATE TABLE テーブル (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL
);
おつかれさまでした! ここまで読んだあなたは、もう「データベースがまったくわからない人」ではありません。あとは道場の依頼を全部こなして、自由練習で自分のデータをいじり倒しましょう。手を動かした分だけ、確実に身につきます。