【初心者向け】MySQLのCREATE TABLE文の使い方を徹底解説!データベース設計の第一歩

データベース・SQL

「MySQLでテーブルを作るにはどうすればいいの?」
そんな疑問を持った方は多いのではないでしょうか。

MySQLにおいて、テーブルはデータを保存するための箱のようなもの。

その箱を作るための命令が、CREATE TABLE文です。

この記事では、初心者の方でも迷わずにテーブル作成ができるようにCREATE TABLE文の基本から応用までを、図や例を使いながらわかりやすく解説していきます。

スポンサーリンク

CREATE TABLE文の基本を理解しよう

最もシンプルな書き方

CREATE TABLE テーブル名 (
    カラム名1 データ型,
    カラム名2 データ型,
    カラム名3 データ型
);

実際の例で理解しよう

ユーザー情報を保存するテーブル

CREATE TABLE users (
    id INT,
    name VARCHAR(100),
    email VARCHAR(255)
);

この例では:

  • users:テーブル名(ユーザー情報を入れる箱)
  • id:ユーザーのID番号(整数)
  • name:ユーザーの名前(最大100文字の文字列)
  • email:メールアドレス(最大255文字の文字列)

テーブルのイメージ

作成されるテーブルは、このような形になります:

idnameemail
(空)(空)(空)

データを入れると:

idnameemail
1田中太郎tanaka@example.com
2佐藤花子sato@example.com

重要な用語の解説

テーブル名

  • データを保存する箱の名前
  • 英数字とアンダースコアが使える
  • わかりやすい名前をつける(例:usersproductsorders

カラム名

  • 箱の中に入るデータの項目名(列)
  • どんな情報を保存するかを表す名前
  • 例:idnameemailcreated_at

データ型

  • そのカラムに保存できるデータの種類
  • 例:INT(整数)、VARCHAR(n)(文字列)、DATE(日付)

よく使うデータ型を覚えよう

数値型

INT:整数を保存

age INT  -- 年齢:25、30、45など

DECIMAL(全体桁数, 小数桁数):正確な小数を保存

price DECIMAL(10,2)  -- 価格:1999.99、150.50など

BIGINT:大きな整数を保存

user_count BIGINT  -- ユーザー数:1000000など

文字列型

VARCHAR(文字数):可変長の文字列

name VARCHAR(100)     -- 名前:最大100文字
email VARCHAR(255)    -- メール:最大255文字

TEXT:長い文字列

description TEXT      -- 商品説明など長い文章

CHAR(文字数):固定長の文字列

prefecture CHAR(2)    -- 都道府県コード:01、13など

日時型

DATE:日付のみ

birth_date DATE       -- 誕生日:1990-05-15

DATETIME:日付と時刻

created_at DATETIME   -- 作成日時:2025-06-03 14:30:00

TIMESTAMP:タイムスタンプ

updated_at TIMESTAMP  -- 更新日時(自動更新される)

データ型の選び方

数値を保存する場合

  • 整数 → INT
  • お金や正確な小数 → DECIMAL
  • とても大きな数 → BIGINT

文字を保存する場合

  • 短い文字(名前、タイトル) → VARCHAR
  • 長い文章 → TEXT
  • 決まった長さ(郵便番号、コード) → CHAR

日付・時刻を保存する場合

  • 日付のみ → DATE
  • 日付と時刻 → DATETIME
  • 自動更新される時刻 → TIMESTAMP

制約(ルール)をつけてより安全なテーブルにしよう

制約とは、データの正しさを保つためのルールです。

主な制約の種類

制約名意味効果
PRIMARY KEY主キー重複・NULL値を許さない、テーブルで1つだけ
NOT NULL必須項目空(NULL)の値を許さない
UNIQUE一意性重複する値を許さない
AUTO_INCREMENT自動採番数値が自動で1、2、3…と増加
DEFAULT初期値値が指定されないときのデフォルト値

実際の使用例

基本的な制約付きテーブル

CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(100) NOT NULL,
    email VARCHAR(255) UNIQUE,
    age INT,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

この例の説明:

  • id:主キーで自動採番(1、2、3…と自動で増える)
  • name:必須項目(空にできない)
  • email:重複不可(同じメールアドレスは登録できない)
  • age:年齢(空でもOK)
  • created_at:作成日時(自動で現在時刻が入る)

制約の具体的な効果

PRIMARY KEYの効果

-- これは成功
INSERT INTO users (name, email) VALUES ('田中太郎', 'tanaka@example.com');

-- これはエラー(idが重複)
INSERT INTO users (id, name, email) VALUES (1, '佐藤花子', 'sato@example.com');

NOT NULLの効果

-- これはエラー(nameが空)
INSERT INTO users (email) VALUES ('yamada@example.com');

-- これは成功
INSERT INTO users (name, email) VALUES ('山田次郎', 'yamada@example.com');

UNIQUEの効果

-- 1回目は成功
INSERT INTO users (name, email) VALUES ('鈴木一郎', 'suzuki@example.com');

-- 2回目はエラー(emailが重複)
INSERT INTO users (name, email) VALUES ('高橋二郎', 'suzuki@example.com');

実際の業務でよく使うテーブル例

ECサイトの商品テーブル

CREATE TABLE products (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(200) NOT NULL,
    description TEXT,
    price DECIMAL(10,2) NOT NULL,
    stock_quantity INT DEFAULT 0,
    category_id INT,
    is_active BOOLEAN DEFAULT TRUE,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

ブログの記事テーブル

CREATE TABLE articles (
    id INT PRIMARY KEY AUTO_INCREMENT,
    title VARCHAR(255) NOT NULL,
    content TEXT NOT NULL,
    author_id INT NOT NULL,
    status ENUM('draft', 'published', 'archived') DEFAULT 'draft',
    view_count INT DEFAULT 0,
    published_at DATETIME,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

社員管理テーブル

CREATE TABLE employees (
    id INT PRIMARY KEY AUTO_INCREMENT,
    employee_code VARCHAR(10) UNIQUE NOT NULL,
    first_name VARCHAR(50) NOT NULL,
    last_name VARCHAR(50) NOT NULL,
    email VARCHAR(255) UNIQUE NOT NULL,
    department_id INT,
    position VARCHAR(100),
    salary DECIMAL(10,2),
    hire_date DATE NOT NULL,
    birth_date DATE,
    phone VARCHAR(20),
    address TEXT,
    is_active BOOLEAN DEFAULT TRUE,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

よくある間違いと対策

データ型の選び間違い

間違った例

CREATE TABLE users (
    age VARCHAR(10),        -- 年齢を文字列にしている
    price VARCHAR(20),      -- 価格を文字列にしている
    created_at VARCHAR(50)  -- 日付を文字列にしている
);

正しい例

CREATE TABLE users (
    age INT,                          -- 年齢は整数
    price DECIMAL(10,2),              -- 価格は小数
    created_at DATETIME               -- 日付は日時型
);

なぜ間違いなのか?

  • 数値として計算できない
  • 日付として並び替えできない
  • データサイズが無駄に大きくなる

PRIMARY KEYがない

問題のある例

CREATE TABLE users (
    name VARCHAR(100),
    email VARCHAR(255)
);

改善された例

CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(100),
    email VARCHAR(255)
);

なぜPRIMARY KEYが必要?

  • レコードを一意に識別できる
  • 更新・削除時に確実に対象を指定できる
  • 他のテーブルから参照しやすい

命名規則の不統一

悪い例

CREATE TABLE UserInfo (          -- 大文字小文字が混在
    ID INT,                      -- 大文字
    UserName VARCHAR(100),       -- キャメルケース
    user_email VARCHAR(255),     -- スネークケース
    CreatedAt DATETIME           -- 混在
);

良い例

CREATE TABLE user_info (         -- 全て小文字+アンダースコア
    id INT,                      -- 小文字
    user_name VARCHAR(100),      -- スネークケース
    user_email VARCHAR(255),     -- スネークケース
    created_at DATETIME          -- スネークケース
);

テーブル作成時のベストプラクティス

1. 一貫した命名規則

テーブル名

  • 全て小文字
  • 複数形を使う(usersproductsorders
  • アンダースコア区切り(user_profilesorder_items

カラム名

  • 全て小文字
  • アンダースコア区切り(first_namecreated_at
  • 略語は避ける(descriptiondescにしない)

2. 必須カラムの設定

どのテーブルにも含めるべきカラム

id INT PRIMARY KEY AUTO_INCREMENT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP

3. 適切なデータ型の選択

文字列の長さ

  • 名前:VARCHAR(100)
  • メールアドレス:VARCHAR(255)
  • タイトル:VARCHAR(255)
  • 説明文:TEXT

数値の精度

  • ID:INT
  • 金額:DECIMAL(10,2)
  • 数量:INT
  • パーセンテージ:DECIMAL(5,2)

4. 制約の適切な使用

CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,        -- 主キー
    email VARCHAR(255) UNIQUE NOT NULL,       -- 一意かつ必須
    name VARCHAR(100) NOT NULL,               -- 必須
    age INT CHECK (age >= 0),                 -- 0以上の制約
    status ENUM('active', 'inactive') DEFAULT 'active',  -- 選択肢と初期値
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

IF NOT EXISTSで安全にテーブル作成

基本的な使い方

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

効果

  • テーブルが既に存在する場合はエラーにならない
  • スクリプトの再実行が安全にできる

実用的な例

-- データベースが存在しない場合は作成
CREATE DATABASE IF NOT EXISTS my_app;

-- データベースを選択
USE my_app;

-- テーブルが存在しない場合のみ作成
CREATE TABLE IF NOT EXISTS users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50) UNIQUE NOT NULL,
    email VARCHAR(255) UNIQUE NOT NULL,
    password_hash VARCHAR(255) NOT NULL,
    full_name VARCHAR(100),
    avatar_url VARCHAR(500),
    is_active BOOLEAN DEFAULT TRUE,
    last_login_at DATETIME,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

実践演習:実際にテーブルを作ってみよう

演習1:図書館管理システム

要件

  • 本の情報を管理したい
  • 必要な項目:ID、タイトル、著者、出版社、出版年、ISBN、貸出状況

解答例

CREATE TABLE books (
    id INT PRIMARY KEY AUTO_INCREMENT,
    title VARCHAR(255) NOT NULL,
    author VARCHAR(100) NOT NULL,
    publisher VARCHAR(100),
    published_year INT,
    isbn VARCHAR(13) UNIQUE,
    is_borrowed BOOLEAN DEFAULT FALSE,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

演習2:レストラン予約システム

要件

  • 予約情報を管理したい
  • 必要な項目:ID、顧客名、電話番号、予約日時、人数、特記事項、ステータス

解答例

CREATE TABLE reservations (
    id INT PRIMARY KEY AUTO_INCREMENT,
    customer_name VARCHAR(100) NOT NULL,
    phone VARCHAR(20) NOT NULL,
    reservation_datetime DATETIME NOT NULL,
    party_size INT NOT NULL,
    special_requests TEXT,
    status ENUM('confirmed', 'cancelled', 'completed') DEFAULT 'confirmed',
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

演習3:ECサイトの注文システム

要件

  • 注文情報を管理したい
  • 必要な項目:ID、顧客ID、注文日、合計金額、配送先住所、ステータス

解答例

CREATE TABLE orders (
    id INT PRIMARY KEY AUTO_INCREMENT,
    customer_id INT NOT NULL,
    order_date DATETIME DEFAULT CURRENT_TIMESTAMP,
    total_amount DECIMAL(10,2) NOT NULL,
    shipping_address TEXT NOT NULL,
    status ENUM('pending', 'processing', 'shipped', 'delivered', 'cancelled') DEFAULT 'pending',
    notes TEXT,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

エラーが出たときの対処法

よくあるエラーメッセージ

1. Syntax error

ERROR 1064 (42000): You have an error in your SQL syntax

原因と対処

  • カンマの付け忘れ、括弧の閉じ忘れ
  • SQL文を見直して構文をチェック

2. Duplicate column name

ERROR 1060 (42S21): Duplicate column name 'id'

原因と対処

  • 同じカラム名を重複して定義している
  • カラム名を確認して重複を削除

3. Table already exists

ERROR 1050 (42S01): Table 'users' already exists

原因と対処

  • 同じ名前のテーブルが既に存在
  • IF NOT EXISTSを使うか、別のテーブル名にする

次のステップ:さらに高度なテーブル設計

外部キー制約

CREATE TABLE orders (
    id INT PRIMARY KEY AUTO_INCREMENT,
    customer_id INT,
    product_id INT,
    quantity INT NOT NULL,
    FOREIGN KEY (customer_id) REFERENCES customers(id),
    FOREIGN KEY (product_id) REFERENCES products(id)
);

インデックスの追加

CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    email VARCHAR(255) UNIQUE,
    name VARCHAR(100),
    created_at DATETIME,
    INDEX idx_name (name),
    INDEX idx_created_at (created_at)
);

複合主キー

CREATE TABLE user_roles (
    user_id INT,
    role_id INT,
    assigned_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (user_id, role_id)
);

まとめ

MySQLのCREATE TABLE文は、データベース設計の出発点です。この記事で学んだポイントを整理しましょう。

重要なポイント

  • 基本構文CREATE TABLE テーブル名 (カラム名 データ型, ...)
  • データ型選択:用途に応じて適切な型を選ぶ
  • 制約の活用:PRIMARY KEY、NOT NULL、UNIQUEで データの整合性を保つ
  • 命名規則:一貫した命名でメンテナンス性を向上
  • IF NOT EXISTS:安全なテーブル作成

ベストプラクティス

  • 必ずPRIMARY KEYを設定する
  • created_atとupdated_atを含める
  • 適切な制約でデータの品質を保つ
  • わかりやすい命名を心がける

コメント

タイトルとURLをコピーしました