Q1次のうち主キー(PRIMARY KEY)の説明として正しいものはどれですか。
テーブルの作成と定義変更
この記事は、基礎から複雑なSQL,SQLチューニングまでSQLの実践的なスキルを1からマスターする「SQL入門講座の一部」です。
CREATE TABLEで列名と型を並べてテーブルを作り、PRIMARY KEYやNOT NULLを指定し、ALTER TABLEで列の追加・削除・改名まで実行しながら押さえます。
本講座で学ぶ SQL について
本講座で扱うのは、MySQL / Oracle / PostgreSQL / SQL Server など主要な RDBMS で共通して使える普遍的な SQL 構文です。CREATE TABLE / SELECT / WHERE / JOIN / GROUP BYといった基礎は、どの DB に移っても同じ書き方でそのまま通用します。
ブラウザのコンソールは技術的制約からSQLiteを採用していますが、DB ごとに異なる箇所(型の長さ強制、テーブル一覧の確認方法など)が出てきたら、MySQL ではこう書くのように他 DB の書き方も並べて紹介します。
テーブルとは
リレーショナルデータベースでは、データをテーブル(行と列からなる表)に格納します。1 つのテーブルは列(カラム / column)と行(レコード / row)で構成され、列ごとに格納できる値のデータ型が決まっています。
テーブル設計とは、どんな列を用意し、各列にどんな型を割り当てるかをあらかじめ決めることです。型が決まっていることで、想定外の値が入り込むのを防げます。
CREATE TABLE — テーブルの作成
テーブルを作るにはCREATE TABLE文を使います。テーブル名のあとに丸括弧を書き、その中に列名 + 型をカンマ区切りで並べます。最後の列のあとにはカンマを置きません。
型を最初に固めておくことで、想定外のデータ(数値列に文字列が混ざる等)が入りにくくなります。
-- 列名と型を並べてテーブルを作る
CREATE TABLE book_record (
id INTEGER,
title TEXT,
price INTEGER,
published_on TEXT
);
代表的なデータ型
SQL のデータ型は DB の種類に応じて名前と細部が異なりますが、最初は次の型を覚えておけば十分です。
| 型 | 格納する値 | 用途の例 |
|---|---|---|
| INTEGER | 整数 | id / age / count |
| REAL | 浮動小数点数 | score / weight |
| TEXT | 文字列 | name / address / message |
| BLOB | バイナリ | 画像・音声などのバイト列 |
| NUMERIC | 数値全般(日付・真偽値含む) | date / boolean を兼ねる |
MySQL の VARCHAR / CHAR / DATETIME はどう書く?
MySQL や PostgreSQL ではVARCHAR(255) / CHAR(13) / BOOLEAN / DATETIMEといった型を細かく指定して使います。これらは本講座のコンソールでも構文上はそのまま受け付けますが、長さ強制(VARCHAR(10)で 11 文字目を弾くなど)は MySQL や PostgreSQL のような型を厳密に扱う RDBMSで初めて意味を持ちます。
本講座の演習では、列の型をINTEGER / TEXT / REALを中心にシンプルに書きます。MySQL に移すときはINTEGERをINT、TEXTをVARCHAR(N)やTEXTに置き換えるだけで、CREATE TABLE の構造はそのままにできます。
PRIMARY KEY — 行を一意に識別する列
主キー(PRIMARY KEY、行を一意に識別するための列)は、テーブル内で重複しないかつNULL を許さない値だけが入る列です。社員番号やユーザー ID のように「他と被らず必ず存在する」列を主キーにします。
主キーがあると、特定の 1 行を確実に取得できます。原則として、各テーブルに必ず 1 つ主キーを作成しましょう。
-- PRIMARY KEY を列定義の後ろに付ける
CREATE TABLE member (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
joined_on TEXT
);
INTEGER PRIMARY KEY は自動採番になる
INTEGER PRIMARY KEYと書いた列は、INSERT時に値を省略すると 1 から順番に自動で番号が振られます。MySQL では同じ自動採番をid INT PRIMARY KEY AUTO_INCREMENT、PostgreSQL ではid SERIAL PRIMARY KEYと書きます。本講座のコンソールではINTEGER PRIMARY KEYだけで自動採番が効きます。
値を明示してINSERTした場合はその値が入り、次の自動採番はその次の整数から再開します。
制約違反を体験する — NOT NULL の働き
わざと違反してみてNOT NULLやPRIMARY KEYといった制約(constraint = 列に入る値のルール)を確認しましょう。NOT NULLはその列に NULL を入れさせないルールで、必須項目(名前・メールアドレスなど)に付けておくと、値が抜けた不完全な行の混入を未然に防げます。
冒頭で作成したuserテーブルはname TEXT NOT NULLで定義されています。name列に NULL を入れようとすると、DB はその INSERT を拒否してエラーを返します。
NOT NULLの列に NULL を入れる INSERT は弾かれてエラー。空文字('')は NULL とは別物として扱われるので、空文字での INSERT は通る点に注意します。-- 実践 3 で実行する INSERT (NOT NULL 制約違反を起こす)
INSERT INTO user (id, name, age, city)
VALUES (10, NULL, 30, 'Tokyo');
テーブルの確認と削除
テーブルを作ったあとは、どんな表があるかとその表がどんな列を持っているかを確認したくなります。本講座のコンソールでは次の 2 つで確認します。
- テーブル一覧: SELECT name FROM sqlite_master WHERE type='table';
- 列定義の確認: PRAGMA table_info(表名);
MySQL ではSHOW TABLES;とDESCRIBE 表名;、Oracle ではSELECT table_name FROM user_tables;のように、それぞれ専用の書き方があります。DROP TABLEでテーブルごと消すのは、どの DB でも共通の構文です。
-- ① テーブル一覧を表示
SELECT name FROM sqlite_master WHERE type='table';
-- ② user テーブルの列定義を表示
PRAGMA table_info(user);
-- ③ テーブルを消す
DROP TABLE IF EXISTS book_record;
ALTER TABLE — 既存テーブルの定義変更
運用が始まったあとで「列を 1 つ足したい」「テーブル名を変えたい」となったらALTER TABLEを使います。本講座で扱う主な操作は次の 4 つで、どれも MySQL / PostgreSQL でもほぼ同じ構文で動きます。
| 操作 | 構文 | 用途 |
|---|---|---|
| テーブル名を変える | ALTER TABLE 旧名 RENAME TO 新名; | 表全体の改名 |
| 列を追加する | ALTER TABLE 表名 ADD COLUMN 列名 型; | 新しい属性を増やす |
| 列を削除する | ALTER TABLE 表名 DROP COLUMN 列名; | 不要になった属性を消す |
| 列名を変える | ALTER TABLE 表名 RENAME COLUMN 旧名 TO 新名; | 列の改名 |
MySQL の MODIFY / CHANGE COLUMN / AFTER
MySQL ではALTER TABLE 表名 MODIFY 列 型;で列の型を、CHANGE COLUMN 旧名 新名 型;で列名と型を同時に、DROP PRIMARY KEY;で主キーを変更できます。
-- 表全体の改名
ALTER TABLE user RENAME TO user_record;
-- 列の追加(末尾に email 列が増える)
ALTER TABLE user_record ADD COLUMN email TEXT;
-- 列名の変更
ALTER TABLE user_record RENAME COLUMN city TO area;
-- 列の削除
ALTER TABLE user_record DROP COLUMN email;
理解度チェック
まずは1問ずつ答えてみましょう。
Q2本講座のコンソールでuserテーブルの列定義を確認したいとき、最も適切な書き方はどれですか。
Q3本講座のコンソールでALTER TABLEを使うときの挙動として正しいものはどれですか。