まず開いてみる
最初の例題の下にあるボタンを押してください。新しいタブで Planche が開き、ショップデータベースが読み込まれています。データベースはページ内で扱われるため、ここでの変更が他のマシンに届くことはありません。最初の状態に戻したいときは、ウェルカム画面からサンプルを読み込み直してください。
テーブルは表である
これを実行してみてください。categories という名前のテーブルの中身を全部くださいという意味です。
1
SELECT * FROM categories;
結果 — 33 行のうち先頭 5 行
| id | name | description | parent_id | sort_order | is_active |
|---|---|---|---|---|---|
| 1 | Electronics | Electronics and related products | NULL | 0 | 1 |
| 2 | Laptops | Laptops in Electronics | 1 | 1 | 1 |
| 3 | Phones | Phones in Electronics | 1 | 2 | 1 |
| 4 | Tablets | Tablets in Electronics | 1 | 3 | 1 |
| 5 | Audio | Audio in Electronics | 1 | 4 | 1 |
ブラウザの別タブで Planche が開き、サンプルデータベースを読み込んだ状態でこのクエリが入ります。このページの例はどれも同じタブを使い回します。F9 を押すまで実行はされません。
返ってくる表がテーブルです。まず3つの用語を確認します。
- 列は上端に並ぶ見出しのひとつです。
id、name、descriptionなど。テーブルのどの項目も同じ6つを持っていて、この名前がそのままクエリに打ち込む名前になります。 - 行は表を縦に1本たどった横一列で、これがひとつのものにあたります。ここでは1行が1つのカテゴリです。33行あるので、このショップにはカテゴリが33個あります。
- セルは行と列が交わるところ、つまり値ひとつです。たとえば、あるカテゴリの名前です。
このデータベースのテーブルはどれも同じ形です。products は1行が1商品、orders は1行が1注文、customers は1行が1顧客。違うのは、どんな列を持っているかだけです。
空のセルには名前がある
2
SELECT id, name, parent_id
FROM categories
LIMIT 8;
結果 — 8 行のうち先頭 5 行
| id | name | parent_id |
|---|---|---|
| 1 | Electronics | NULL |
| 2 | Laptops | 1 |
| 3 | Phones | 1 |
| 4 | Tablets | 1 |
| 5 | Audio | 1 |
parent_id を見てください。数字が入っている行と、NULL と表示される行があります。この列は「このカテゴリがどのカテゴリの中にあるか」を表します。ノートパソコンは家電の中にあります。そして最上位のカテゴリはどこにも属していないので、入れる値がありません。
NULL は「ここには値がない」という意味です。ゼロの一種としてではなく、それ自体ひとつの考え方として覚える価値があります。実際、ゼロではないからです。
- NULL は
0ではありません。ゼロは測った結果の数字で、NULL は測っていないという事実です。 - NULL は空文字でもありません。名前が空欄で記録されている顧客と、名前を一度も記録していない顧客は別物です。
NULL は通常の値とは異なる比較規則に従います。詳しくは3つめのレッスンで扱います。ここでは、空のセルが単なる空欄ではなく、値が不明であることを示すと覚えておいてください。
行にはそれぞれ固有の番号がある
いちばん左の列は id で、ちょうど1行だけに属し、二度と使い回されない番号です。これが行の主キーです。他の何かがこの行を指すときに、あとから変わりうる名前に頼らずに済むための仕組みです。
出会うテーブルのほとんどが主キーを持っていて、たいていは id という名前です。
なぜ1つではなく23個のテーブルなのか
ショップは原理上、巨大な表1枚でも表せます。1行が1注文で、顧客の名前も住所も、商品も価格もその行に繰り返し書いておけばいい。データベースがそう作られていないのには、身も蓋もない理由があります。引っ越した顧客が1人いるだけで、その人の過去の注文すべてを直して回らなければならず、直し漏れた行がそのまま「他と食い違う事実」になるからです。
そこで、種類ごとにテーブルを分け、行どうしは主キーで指し合います。products.category_id は categories.id を持ち、orders.customer_id は customers.id を持ちます。他のテーブルの行を指す列を外部キーと呼び、これをたどる操作が4つめのレッスンで扱う結合です。
だからこそ、テーブルにどんな列があるかを調べる場所が要ります。サンプルデータベースのページに、全テーブル・全列と、どの列がどのテーブルを指しているかがまとまっています。別タブに開いたままにしておいてください。毎日SQLを書いている人でも、スキーマは手元に置いて書きます。
クエリは質問で、答えもまたテーブル
1行1列、数字ひとつ。これも立派なテーブルで、ただとても小さいだけです。そしてこれがSQLの考え方そのものです。質問を投げると、400行だろうと1行だろうと、返ってくるものはいつも同じ長方形の形をしています。
この答えがデータベースのどこにも保存されていないことにも注意してください。400という数はどこにも記録されていません。聞かれたときにデータベースが数えたのです。役に立つクエリのほとんどはこの型で、答えを探してくるのではなく計算して返します。
自分で実行してみる
ワークスペース上部のエディタでクエリを書き、F9 で実行します。カーソルがある文だけを実行したいときは Ctrl / ⌘ + Enter です。結果は下のグリッドに出て、行数は最下部に表示されます。
左のパネルは同じデータベースをツリーで見せています。main を開いて Tables を開き、テーブルをダブルクリックすれば、何も書かずに中身を見られます。クエリを書く前にテーブルの中身を確かめるには、たいていこれがいちばん速い方法です。
このページの例題はそれぞれ自分のタブで開くので、書き換えて実行して元に戻す、という往復をしても作業中の場所を失いません。
うまくいかないとき
必ずうまくいかないときが来ます。メッセージは短く、そのままの意味です。列名を打ち間違えるとこうなります。
no such column: naem
メッセージは末尾から読んでください。データベースが見つけられなかったものの名前が、たいていそこに書いてあります。最初のうちのエラーはほぼ3種類です。列名の打ち間違い、思っていたのと違うテーブルにある列、そして文字列を囲むクォートの抜けです(SQLで文字列は 'paid' のようにシングルクォートで囲みます。ダブルクォートは別の意味になります)。
エラーが出たということは、何も実行されなかったということです。文はまるごと拒否されるので、失敗したクエリが何かを変えてしまうことはありません。
次は
テーブル、行、列、NULL が何かを押さえ、クエリを実行して結果を読めるようになりました。次のレッスンは、ほぼすべてのクエリを組み立てている4つの句です。