CREATE TABLE はデータベースに新しいテーブルを追加します。テーブル名を付け、カラムを列挙し、それぞれにデータ型と、値が従うべきルール(制約)を指定します。例は PostgreSQL、MySQL、SQLite、SQL Server で動作します。
CREATE TABLE の使い方
テーブル名を指定し、続けてカラムを括弧内にカンマ区切りで列挙します。各カラムには名前とデータ型、必要に応じて PRIMARY KEY、NOT NULL、UNIQUE、DEFAULT、CHECK などの制約を指定します:
CREATE TABLE table_name (
column_name data_type constraints,
another_column data_type constraints
);
CREATE TABLE customers (
id INTEGER PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(255) UNIQUE,
country CHAR(2) DEFAULT 'US',
signed_up DATE
);
INSERT INTO customers (id, name, email, signed_up)
VALUES (1, 'Ana Lima', 'ana@example.com', '2026-03-02');
SELECT * FROM customers;
-- Output:
-- id | name | email | country | signed_up
-- ---+----------+-----------------+---------+-----------
-- 1 | Ana Lima | ana@example.com | US | 2026-03-02
新しいテーブルは行を挿入するまで空のままです。この INSERT では country を省略したため、行にはデフォルト値の US が入りました。
知っておきたいルール
-
SQLite は型や長さを強制しません。他のデータベースならカラムに合わない値を拒否しますが、SQLite はそのまま保存します。チェックさせるには閉じ括弧の後に
STRICTを追加します(STRICT テーブルで使える型はINT、INTEGER、REAL、TEXT、BLOB、ANYのみです)。
CREATE TABLE products (
sku VARCHAR(5),
quantity INTEGER
);
-- SQLite stores this row; other databases reject it with an error
INSERT INTO products VALUES ('LAMP-001', 'twelve');
SELECT sku, quantity FROM products;
-- Output (SQLite):
-- sku | quantity
-- ---------+---------
-- LAMP-001 | twelve
-
外部キーはカラム定義内の
REFERENCESではなく、独立したFOREIGN KEY行で宣言してください。MySQL 8 は短い形式を受け付けますが、無視してしまいます。SQLite はPRAGMA foreign_keys = ON;を実行した後でのみ外部キーを強制し、これは接続ごとに実行する必要があります。 -
テーブルが既に存在すると CREATE TABLE は失敗します。代わりにスキップさせるには
CREATE TABLE IF NOT EXISTSと書きます。 -
MySQL では
TEXTカラムにDEFAULTやUNIQUEを設定できません。ここでの例のようにVARCHAR(n)を使ってください。
代替構文
自動採番の ID の書き方はデータベースごとに異なります:
| データベース | 自動採番の ID カラム |
|---|---|
| PostgreSQL | id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY |
| MySQL | id INT AUTO_INCREMENT PRIMARY KEY |
| SQLite | id INTEGER PRIMARY KEY |
| SQL Server | id INT IDENTITY(1,1) PRIMARY KEY |
INSERT で ID を省略すると、データベースが次の番号を自動で入れます。
SQL Server には真偽値や日時のカラムにも独自の型名があり、IF NOT EXISTS もありません。BOOLEAN の代わりに BIT(1 と 0)を、日時には DATETIME2 を使い(SQL Server の TIMESTAMP は日付ではなく行のバージョン番号です)、テーブル作成前に OBJECT_ID で存在を確認します:
-- SQL Server
IF OBJECT_ID('users', 'U') IS NULL
CREATE TABLE users (
id INT IDENTITY(1,1) PRIMARY KEY,
email VARCHAR(255) NOT NULL UNIQUE,
is_active BIT NOT NULL DEFAULT 1,
created_at DATETIME2 NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE はいつ使うべき?
すべてのテーブルは CREATE TABLE から始まりますが、選ぶカラムや制約によって解決できる問題が異なります。
新しい種類のデータを保存する
顧客、書籍、請求書など、アプリケーションが管理する対象ごとに専用のテーブルを用意し、その属性ごとにカラムを作って、値に合った型を指定します。
すべての行に一意の ID を付ける
PRIMARY KEY は 2 つの行が同じ識別子を持つのを防ぐため、常に特定の 1 行を検索・更新・参照できます。行の採番はデータベースに任せるか(上の「代替構文」を参照)、2 つの値の組で行を識別する場合は 2 つのカラムを組み合わせます。
不正なデータや欠損データを防ぐ
制約はルールに違反する行を拒否します。必須カラムには NOT NULL、メールアドレスなどの値には UNIQUE、許容範囲には CHECK を使います。DEFAULT は INSERT で省略されたカラムに値を入れます。
関連するテーブルをつなぐ
FOREIGN KEY はカラムが別のテーブルの行を参照するようにするため、存在しない顧客を指定した注文は作れません。ON DELETE CASCADE を追加すると、親の行を削除したときにそれを参照する行も削除されます。
クエリ結果をテーブルとして保存する
CREATE TABLE ... AS SELECT は 1 つのステートメントでテーブルを作成し、クエリの結果を格納します。スナップショットやレポート用のテーブル、変更前の行のバックアップに使えます。
CREATE TABLE の実例
エラーメッセージは PostgreSQL のものです。他のデータベースも同じ行を拒否しますが、文言は異なります。
2 カラムのキーを持つ中間テーブル
学生は多くのコースを受講し、コースには多くの学生がいます。enrollments テーブルがこれらをつなぎ、その主キーは ID の組です。そのため学生は多くのコースに参加できますが、同じコースに 2 回参加することはできません:
CREATE TABLE enrollments (
student_id INTEGER NOT NULL,
course_id INTEGER NOT NULL,
enrolled_on DATE,
PRIMARY KEY (student_id, course_id)
);
INSERT INTO enrollments VALUES (1, 101, '2026-09-01');
INSERT INTO enrollments VALUES (1, 102, '2026-09-01');
INSERT INTO enrollments VALUES (1, 101, '2026-09-08');
-- ERROR: duplicate key value violates unique constraint "enrollments_pkey"
-- DETAIL: Key (student_id, course_id)=(1, 101) already exists.
SELECT * FROM enrollments;
-- Output:
-- student_id | course_id | enrolled_on
-- -----------+-----------+------------
-- 1 | 101 | 2026-09-01
-- 1 | 102 | 2026-09-01
ルールに従うサインアップ
すべてのアカウントには、他のアカウントが使っていないメールアドレスと 1 つ以上のシートが必要です。新規アカウントは無料プランの 1 シートから始まります:
CREATE TABLE accounts (
id INTEGER PRIMARY KEY,
email VARCHAR(255) NOT NULL UNIQUE,
tier VARCHAR(20) NOT NULL DEFAULT 'free',
seats INTEGER NOT NULL DEFAULT 1 CHECK (seats > 0)
);
INSERT INTO accounts (id, email) VALUES (1, 'sam@example.com');
SELECT * FROM accounts;
-- Output:
-- id | email | tier | seats
-- ---+-----------------+------+------
-- 1 | sam@example.com | free | 1
INSERT INTO accounts (id, email) VALUES (2, 'sam@example.com');
-- ERROR: duplicate key value violates unique constraint "accounts_email_key"
INSERT INTO accounts (id, email, seats) VALUES (3, 'kim@example.com', 0);
-- ERROR: new row ... violates check constraint "accounts_seats_check"
INSERT INTO accounts (id) VALUES (4);
-- ERROR: null value in column "email" ... violates not-null constraint
必ず顧客に紐づく注文
各注文は顧客を参照します。外部キーは存在しない顧客への注文を拒否し、ON DELETE CASCADE は顧客が削除されたときにその顧客の注文も削除します。SQLite では先に PRAGMA foreign_keys = ON; を実行してください。
CREATE TABLE customers (
id INTEGER PRIMARY KEY,
name VARCHAR(100) NOT NULL
);
CREATE TABLE orders (
id INTEGER PRIMARY KEY,
customer_id INTEGER NOT NULL,
total DECIMAL(10,2),
FOREIGN KEY (customer_id) REFERENCES customers(id) ON DELETE CASCADE
);
-- Input: customers
-- id | name
-- ---+-----------
-- 1 | Ana Lima
-- 2 | Ben Okafor
-- Input: orders
-- id | customer_id | total
-- ---+-------------+------
-- 10 | 1 | 25.00
-- 11 | 1 | 60.00
-- 12 | 2 | 42.50
INSERT INTO orders VALUES (13, 99, 15.00);
-- ERROR: ... violates foreign key constraint "orders_customer_id_fkey"
-- DETAIL: Key (customer_id)=(99) is not present in table "customers".
DELETE FROM customers WHERE id = 1;
-- Output (orders after the DELETE):
-- id | customer_id | total
-- ---+-------------+------
-- 12 | 2 | 42.50
アクティブな顧客のスナップショット
今年注文した顧客を専用のテーブルにコピーし、新しい注文が入っても変わらないキャンペーンリストを作ります:
-- Input: customers
-- customer_id | name | email | last_order_date
-- ------------+------------+-------------------+----------------
-- 1 | Ana Lima | ana@example.com | 2026-03-18
-- 2 | Ben Okafor | ben@example.com | 2025-11-02
-- 3 | Chloe Park | chloe@example.com | 2026-06-30
-- 4 | Dev Shah | dev@example.com | NULL
CREATE TABLE active_customers AS
SELECT customer_id, name, email
FROM customers
WHERE last_order_date >= '2026-01-01';
-- SQL Server has no CREATE TABLE ... AS. Use SELECT ... INTO:
SELECT customer_id, name, email
INTO active_customers
FROM customers
WHERE last_order_date >= '2026-01-01';
-- Output (active_customers):
-- customer_id | name | email
-- ------------+------------+------------------
-- 1 | Ana Lima | ana@example.com
-- 3 | Chloe Park | chloe@example.com
新しいテーブルにはカラムとその型、行がコピーされますが、主キーやその他の制約はコピーされません。必要であれば ALTER TABLE で追加してください。
CREATE TABLE の関連資料
このブログの記事:
- SQL 一時テーブルガイド: セッション中だけ存在するテーブル
- SQL ALTER TABLE でカラムを追加: 作成後のテーブルを変更する
- SQL の複合主キー: 複数のカラムで構成されるキー
- PostgreSQL での外部キーの使い方: 外部キーと削除時の動作を詳しく解説
- データベースのリレーションガイド: 互いにつながるテーブルの設計
- SQL INSERT ステートメント: 新しいテーブルに行を追加する
- SQL テーブル作成ツール: CREATE TABLE ステートメントを手書きせずブラウザで作成
公式ドキュメント:
Beekeeper Studioは無料のオープンソースのデータベースGUIです
これまで使った中で最高のSQLクエリ&エディタツールです。データベースの管理に必要なものがすべて揃っています。 - ⭐⭐⭐⭐⭐ Mit
Beekeeper Studioは高速で直感的、そして使いやすいツールです。多数のデータベースに対応し、Windows、Mac、Linuxで快適に動作します。
Beekeeper Studio 利用者の声
「Beekeeper Studio は以前の SQL ワークフローを完全に置き換えました。高速で直感的、データベース作業がまた楽しくなりました。」
「多くのデータベース GUI を試しましたが、Beekeeper は機能とシンプルさのバランスが完璧です。とにかくちゃんと動きます。」