CREATE DATABASE と CREATE TABLE

このレッスンで分かること

  • DDL (CREATE 等) は構造を作る、DML (SELECT 等) は中身を扱う
  • CREATE TABLE 名前 (列名 型 制約, ...) の形で作ります
  • 冪等性が必要なら IF NOT EXISTS を付けます

CREATE DATABASE と CREATE TABLE とは

データベースとテーブルの作成を、ターミナルで実際に操作しながら学びます。本レッスンでは、CREATE DATABASE と CREATE TABLE の基本から実際の使いどころまでを整理し、現場で迷わず使える形に落とし込みます。

なぜ重要か

ここまでは既にあるテーブルからデータを取り出す側に立ってきましたが、実務ではテーブルそのものを「設計して用意する」工程が必ず先にあります。アプリのバックエンド担当に「ユーザ情報を保存したいから受け取り口を作って」と頼まれた時、最初の一手は CREATE DATABASE でアプリ専用の入れ物を作り、その中に CREATE TABLE でデータの型を定義することです。テーブル設計を雑にすると、後から ALTER TABLE で型を直したり、データを移し替えたりと、コストの大きな作業が連鎖します。だからこそ最初の CREATE 文を丁寧に書ける力は、SQL を「読む」から「設計する」フェーズに進む最初の関門になります。

DDL と DML

SQL の命令文は大きく次の 2 系統に分かれます。

  • DDL (Data Definition Language) — テーブルの構造を作る・変える CREATE ALTER DROP TRUNCATE など
  • DML (Data Manipulation Language) — テーブルの中身を出し入れする SELECT INSERT UPDATE DELETE など
系統代表的な命令目的
DDLCREATE ALTER DROP構造の定義・変更
DMLSELECT INSERT UPDATE DELETE中身の操作
DCLGRANT REVOKE権限の付与・剥奪
TCLBEGIN COMMIT ROLLBACKトランザクション制御

この章は DDLDML をひとつながりで学ぶ章です。最初のレッスンはその入口で、まずは CREATE 系を集中的に押さえます。SELECT / WHERE / JOIN のような「読み出し系」は前章までで一通り扱いましたので、ここからは「書き込み・設計系」の世界に足を踏み入れます。

データベース・スキーマ・テーブルの関係

本レッスンの演習環境 (PostgreSQL 互換) では、CREATE DATABASE の代わりに CREATE SCHEMA でデータの入れ物を作り、SET search_path で対象を切り替えます。MySQL / TiDB では「データベース」と「スキーマ」がほぼ同義で、CREATE DATABASEUSE という書き方になりますが、役割は同じです。本番運用では「アプリ 1 つ = データベース (スキーマ) 1 つ」の対応が一般的で、それを跨いだ JOIN は基本的に避けます。

構文の基本

SQL クエリ

-- データベース (スキーマ) を作る CREATE SCHEMA shop_db; -- 以降の操作を shop_db に向ける SET search_path TO shop_db; -- テーブルを作る CREATE TABLE users ( id INT PRIMARY KEY, name VARCHAR(100) NOT NULL, email VARCHAR(255), created_at TIMESTAMP );

CREATE TABLE の中身は「列名 型 制約」を 1 行ずつカンマ区切りで並べたものです。最後の列の後ろに余分なカンマを置くと文法エラーになる点に注意してください。

CREATE 文の処理フロー

diagram (will load when visible)

図の流れを順序リストで書き直すと、次の通りです。

  1. CREATE SCHEMA (MySQL/TiDB なら CREATE DATABASE) で器を作る
  2. SET search_path (MySQL/TiDB なら USE) で対象を切り替える
  3. CREATE TABLE を発行する
  4. DBMS が列定義と制約を解釈する
  5. ストレージにメタ情報を書き込む
  6. これで INSERT を受け付けられる状態になる

テーブルは「列の型と並び」というメタ情報だけが先に作られて、行はまだ 0 行です。続く INSERT 文で初めて中身が入ります。

代表例

ユーザ一覧と注文一覧という、よくある 2 つのテーブルを作る例です。

SQL クエリ

CREATE TABLE users ( id INT PRIMARY KEY, name VARCHAR(100) NOT NULL, email VARCHAR(255) NOT NULL, created_at TIMESTAMP NOT NULL ); CREATE TABLE orders ( id INT PRIMARY KEY, user_id INT NOT NULL, total_amount INT NOT NULL, ordered_at TIMESTAMP NOT NULL );

users.idorders.id がそれぞれの主キーで、orders.user_id で users を参照する設計です。テーブルを作った直後は両方とも空なので、SELECT * FROM users; を実行しても 0 行が返ります。

IF NOT EXISTS で安全に書く

既に同名のテーブルが存在すると CREATE は失敗します。シードスクリプトや CI で何度も流す場合は IF NOT EXISTS を付けて冪等にしておくと安心です。

SQL クエリ

CREATE TABLE IF NOT EXISTS users ( id INT PRIMARY KEY, name VARCHAR(100) NOT NULL );

テーブル名・列名は小文字スネークケース (例 created_at) が一般的です。MySQL/TiDB は OS によっては大文字小文字を区別するので、慣習に揃えると後々のトラブルが減ります。テーブル名は複数形 (users, orders)、列名は単数形にするチームが多いです。

アプリ開発では生の CREATE TABLE を書く機会は少なく、drizzle-kitprisma migrate のようなマイグレーションツールが SQL を自動生成します。それでも生成された SQL を読んで意図を確認するスキルは必要で、その下地が本レッスンです。

CREATE TABLE を流す前に SET search_path (MySQL/TiDB なら USE データベース名) を忘れると、デフォルトのスキーマに余計なテーブルができてしまいます。スクリプト先頭で必ず対象を切り替えましょう。

この章のポイント

ここまでの要点 DDL は構造、DML は中身。CREATE SCHEMA (MySQL/TiDB は CREATE DATABASE) → search_path 切替 (MySQL/TiDB は USE) → CREATE TABLE の順。冪等性は IF NOT EXISTS。テーブル名は複数形・スネークケース。

まとめ

  • DDL はテーブルの「型紙」を作る命令、DML は中身を出し入れする命令
  • CREATE SCHEMA (MySQL/TiDB は CREATE DATABASE) → search_path 切替 (MySQL/TiDB は USE) → CREATE TABLE の順で土台を作る
  • 列定義は「列名 型 制約」をカンマ区切りで並べる
  • 冪等性が必要なら IF NOT EXISTS を付ける
  • テーブル作成直後は 0 行、INSERT で初めて行が入る

次のレッスン

次は データ型の選び方 です。SQLにおける適切なデータ型の選択方法を、具体的な例を交えながらSQLで実践的に解説します。

事前確認 — 進む前に次の 3 つができることを確認しましょう。

  1. CREATE DB/TABLE の要点を自分の言葉で説明できる
  2. このレッスンの最小コード (または操作手順) を見ずに書ける
  3. 練習問題やクイズで間違えた箇所を読み直して理解した

理解度チェック (30 秒)

Q. CREATE DB/TABLE とは何か、1 文で説明してください。

この章のポイント

A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。

関連レッスン

テーブル構造

schema.sql

-- 既にデータベースが用意されている状態を想定。 -- 空のスキーマ。あなたが CREATE TABLE2 つのテーブルを作ります。 SELECT 1;

期待される出力

table_namecolumn_count
categories2
products4

ヒント

query.sql
query.sql
学習モード
コードの実行結果
データベースを初期化中...