SQL Lab
第一部 DB 基礎編 · 第 1 章 · 約 25

テーブルを読む、作る

顧客一覧の表を開き、行・列・主キー・型・NULL に名前を付ける。自分でテーブルを作って行を入れる。

この章で答える問い
  1. 表の行・列・左端の番号・空欄は、それぞれ何と呼ばれ、どういう約束があるのか
  2. 列には「型」があるとはどういうことか
  3. 自分でテーブルを作って行を入れるには、何を書くか

実物: 顧客一覧の表

customers を全部
期待: 10 行 5 列。email が空の行が 2 つ

この表を見ながら名前を付けていく。横 1 列が(レコード)で、1 行が 1 人の顧客。縦 1 列が(カラム)で、nameemail のように名前が付いている。表全体がテーブルで、同じ形の行の集まりだ。

id の列: 主キー

左端の id は 1 から 10 の番号で、同じ番号の行はない。この「行を一意に指す列」を主キー(PRIMARY KEY)と呼ぶ。 主キーは重複してはいけないし、空でもいけない。上のパネル「いまあるテーブル」で 🔑 が付いているのがそれだ。

なぜ名前を主キーにしないのか。同姓同名がいるし、名前は変わる。主キーは他のテーブルから「この顧客」を指すのに使うので(第 4 章)、 変わる値を使うと、指している側を全部直す羽目になる。だから意味のない連番を使う。

空欄: NULL

伊藤さんと小林さんの email が空だ。表示は NULL になっている。NULL は「値がない」ことを表す特別な印で、空文字 '' とも 0 とも違う。 「メールが空文字」ではなく「メールが登録されていない」だ。

NULL には、ここで一度だけ体験しておくべき性質がある。実行する前に、返る行数を予測してほしい。

email が NULL の人を = で探す
期待: 予測してから実行
実行する前に予測する

0 行のはずだ。NULL と何かを = で比べた結果は、真でも偽でもなく「不明」になる。WHERE は真の行しか残さないので、不明の行は落ちる。 NULL かどうかを聞くには専用の書き方を使う。

IS NULL で探す
期待: 2 行

WHERE の詳しい使い方は次の章でやる。ここでは「NULL は = では見つからない、IS NULL を使う」だけ覚える。 この性質は第 2 章と第 6 章で、もっと意外な形で顔を出す。

列の型

各列には「どんな値が入るか」の決まりがある。実物を見る。

テーブルの定義を見る
期待: 1 行。Create Table の列に定義文

Create Table の列に、このテーブルを作ったときの文が入っている。name VARCHAR(40) NOT NULL のように、 列ごとに「型」と「NULL を許すか」が書いてある。型は、その列に入れられる値の種類と大きさで、合わない値は入らない。よく使うのはこの 6 つ。

入るものこの店での例注意
INT / BIGINT整数id、数量、価格(円)INT は ±21 億まで。明細のような増え続ける id は BIGINT
DECIMAL(10,2)正確な小数税率、外貨の金額FLOAT / DOUBLE は誤差が出るので金額に使わない
VARCHAR(n)n 文字までの文字列名前、メール、商品名長文は TEXT
DATETIME日時注文日時、登録日時タイムゾーンを持たない。UTC で入れる運用が多い
BOOLEAN真偽(実体は 0 / 1)有効フラグ
JSON構造化データ配送先の付加情報検索条件にする値は普通の列に出す

NOT NULL が付いた列は NULL を入れられない。パネルの NN がそれ。「入っていなくてもいい列」以外は NOT NULL にするのが設計の基本で、 NULL を許した列は、この後ずっと「NULL のときどうするか」を考える必要が付いて回る。 ここまでに名前を付けた、行・列・テーブル・主キー・NULL・型を 1 枚にまとめる。

customers(10 行のうち 3 行)idnameemailtiercreated_at1佐藤 陽菜hina@example.comgold2025-11-03 13:512鈴木 大輔daisuke@example.comregular2025-12-14 09:525伊藤 結衣NULLregular2026-02-02 15:07← 1 行 = 1 人の顧客(レコード)↑ 列(カラム)id は主キー。行を一意に指し、重複も NULL も不可。NULL は「値がない」印。空文字とも 0 とも別物。列には型がある: INT / VARCHAR(40) / DATETIME。NOT NULL の列に NULL は入らない。
テーブルは同じ形の行の集まり。id が行を指し、NULL は値がない印で、列には型がある。

作る、入れる、読む

チケットの本題(一覧画面)は、もう SELECT * FROM customers で足りている。ここではテーブルを自分で作る側を体験する。 クーポンのテーブルを作る。作ったら、上のパネルの「更新」を押すと現れる。

coupons テーブルを作る
期待: エラーなく終わる(結果の表はない)

CREATE TABLE 名前 (列の定義, …)AUTO_INCREMENT は「入れるときに番号を自動で振る」、DEFAULT は「指定しなかったときの値」。expires_at だけ NULL を許している(期限のないクーポンがあるので)。

1 行入れる
期待: 影響した行数 1
まとめて入れる
期待: 影響した行数 3
読む
期待: 4 行。id は 1〜4、created_at は今の時刻

INSERT INTO テーブル (列, …) VALUES (値, …)。書かなかった列は AUTO_INCREMENT や DEFAULT で埋まり、 NOT NULL で DEFAULT もない列を書き忘れるとエラーになる。エラーになることを確かめておく。

NOT NULL の列を省く
期待: エラー。Field 'code' doesn't have a default value

DB は不正なデータを入れない。この「入れない」がアプリのバグからデータを守る最後の砦になる。 1 本目の INSERT で 5 列がどう埋まったかを、列の定義と並べて見る。

INSERT INTO coupons (code, discount) VALUES ('WELCOME10', 10)定義入った値idINT AUTO_INCREMENT PRIMARY KEY1codeVARCHAR(20) NOT NULL'WELCOME10'discountINT NOT NULL10expires_atDATETIME NULLNULLcreated_atDATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP今の時刻書かなかった → 自動採番書いた値書いた値書かなかった → NULL 許可なので NULL書かなかった → DEFAULT の値INSERT INTO coupons (discount) VALUES (15)idcodediscountexpires_atcreated_at埋められない15NULL今の時刻code は NOT NULL で DEFAULT なし → エラー
書かなかった列は AUTO_INCREMENT・DEFAULT・NULL 許可のどれかで埋まり、どれもない列を省くとエラーになる。

テーブルは同じ形の行の集まりで、列には型があり、主キーが行を指し、NULL は「値がない」を表して = では見つからない。

確認

メールが登録されていない顧客を探すのに、email = NULL と書いてはいけないのはなぜか。
NULL と何かを = で比べた結果は真でも偽でもなく「不明」になり、WHERE は真の行しか残さないので 1 行も返らない。NULL かどうかを聞くには IS NULL を使う。
INSERT で列を省いても行が入る場合と、エラーになる場合の違いは何か。
AUTO_INCREMENT・DEFAULT・NULL 許可のどれかがある列は、省いてもその決まりで埋まる。NOT NULL で DEFAULT もない列を省くと、埋める値がないのでエラーになる。
主キーに名前ではなく、意味のない連番を使うのはなぜか。
主キーは他のテーブルから「この行」を指すのに使うため、値が変わると指している側を全部直すことになる。名前は同姓同名があり、変わりもするので向かない。

次の章へ

一覧は出せた。次のチケットは「未発送の注文を新しい順に 10 件」で、全行ではなく欲しい行だけを、欲しい順に取り出す必要がある。 WHERE、ORDER BY、LIMIT の出番だ。そして NULL が、もう一度意外な形で出てくる。