【超入門】MySQLのINSERT文の正しい書き方とは?データ追加の基本を完全マスター!

データベース・SQL

「テーブルは作れたけど、どうやってデータを入れるの?」
そんな疑問を持った方に向けて、今回はMySQLでデータを追加する命令である「INSERT文」の使い方を解説します。

INSERTは、MySQLを使う上で必ず必要になる基本操作の一つです。

この記事では、初心者の方でもすぐ実践できるように、文法の基礎から応用、よくあるエラーの対処法までを丁寧にご紹介します。

スポンサーリンク
  1. 基本のINSERT文の書き方
    1. 最もシンプルな構文
    2. 実際の例で理解しよう
    3. 実行前後のテーブルの状態
    4. 重要なルール
  2. カラムの指定方法とパターン
    1. 全てのカラムを指定する場合
    2. 一部のカラムだけを指定する場合
    3. カラム名を省略する場合(非推奨)
  3. 複数行のINSERTで効率アップ
    1. 基本的な複数行INSERT
    2. 実行結果
    3. 複数行INSERTのメリット
  4. AUTO_INCREMENTの扱い方
    1. AUTO_INCREMENTとは
    2. AUTO_INCREMENTカラムは省略できる
    3. 明示的に値を指定することも可能
    4. AUTO_INCREMENTの動作例
  5. さまざまなデータ型の入れ方
    1. 文字列データ
    2. 数値データ
    3. 日付・時刻データ
    4. 真偽値(BOOLEAN)データ
    5. NULLデータ
    6. JSON データ(MySQL 5.7以降)
  6. よくあるINSERTエラーと解決策
    1. 1. カラム数と値の数が合わない
    2. 2. 一意性制約違反(UNIQUE制約)
    3. 3. NOT NULL制約違反
    4. 4. データ型不整合
    5. 5. 存在しないカラム名
  7. 実際の業務でよく使うINSERTパターン
    1. ユーザー登録
    2. 商品登録
    3. 注文データの登録
    4. ログデータの登録
    5. 設定データの登録
  8. INSERT文の応用テクニック
    1. INSERT … SELECT で他のテーブルからデータをコピー
    2. ON DUPLICATE KEY UPDATE で重複時の動作を制御
    3. REPLACE INTO による上書きINSERT
    4. INSERT IGNORE でエラーを無視
  9. パフォーマンスを考慮した INSERT
    1. 大量データのINSERT
    2. インデックスを考慮したINSERT
  10. 安全なINSERTのための注意点
    1. SQLインジェクション対策
    2. データの検証
    3. トランザクション管理
  11. デバッグとトラブルシューティング
    1. INSERTの動作確認
    2. よくある問題と解決法
  12. まとめ

基本のINSERT文の書き方

最もシンプルな構文

INSERT INTO テーブル名 (カラム1, カラム2, カラム3) VALUES (値1, 値2, 値3);

実際の例で理解しよう

usersテーブルの構造

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

1件のデータを追加

INSERT INTO users (name, email, age) VALUES ('田中太郎', 'tanaka@example.com', 25);

この例では:

  • users:データを追加するテーブル名
  • (name, email, age):データを入れるカラムを指定
  • VALUES ('田中太郎', 'tanaka@example.com', 25):それぞれのカラムに入れる値

実行前後のテーブルの状態

実行前

idnameemailage
(空のテーブル)

実行後

idnameemailage
1田中太郎tanaka@example.com25

重要なルール

カラム名と値の数は必ず一致

-- ❌ 間違い:カラム3つ、値2つ
INSERT INTO users (name, email, age) VALUES ('田中太郎', 'tanaka@example.com');

-- ✅ 正しい:カラム3つ、値3つ
INSERT INTO users (name, email, age) VALUES ('田中太郎', 'tanaka@example.com', 25);

文字列はシングルクォートで囲む

-- ✅ 正しい
INSERT INTO users (name, email) VALUES ('田中太郎', 'tanaka@example.com');

-- ❌ 間違い
INSERT INTO users (name, email) VALUES (田中太郎, tanaka@example.com);

数値はクォート不要

-- ✅ 正しい
INSERT INTO users (age) VALUES (25);

-- ⚠️ 動作するが推奨しない
INSERT INTO users (age) VALUES ('25');

カラムの指定方法とパターン

全てのカラムを指定する場合

INSERT INTO users (name, email, age) VALUES ('佐藤花子', 'sato@example.com', 30);

一部のカラムだけを指定する場合

-- 年齢を省略(NULLまたはデフォルト値が入る)
INSERT INTO users (name, email) VALUES ('山田次郎', 'yamada@example.com');

カラム名を省略する場合(非推奨)

-- テーブルの全カラムを順番通りに指定
INSERT INTO users VALUES (NULL, '鈴木一郎', 'suzuki@example.com', 28);

なぜ非推奨?

  • テーブル構造が変わるとエラーになる
  • 何の値を入れているかわかりにくい
  • メンテナンス性が悪い

複数行のINSERTで効率アップ

基本的な複数行INSERT

INSERT INTO users (name, email, age)
VALUES
    ('佐藤花子', 'sato@example.com', 30),
    ('鈴木次郎', 'suzuki@example.com', 28),
    ('高橋三郎', 'takahashi@example.com', 35);

実行結果

idnameemailage
1田中太郎tanaka@example.com25
2佐藤花子sato@example.com30
3鈴木次郎suzuki@example.com28
4高橋三郎takahashi@example.com35

複数行INSERTのメリット

パフォーマンスが向上

  • 1回のSQL実行で複数行を処理
  • データベースへの接続回数が減る
  • トランザクションの回数が減る

コードが簡潔

  • 何度もINSERT文を書く必要がない
  • エラーハンドリングが楽

実際の処理時間比較例

-- 遅い方法:1件ずつ3回実行
INSERT INTO users (name, email) VALUES ('ユーザー1', 'user1@example.com');
INSERT INTO users (name, email) VALUES ('ユーザー2', 'user2@example.com');
INSERT INTO users (name, email) VALUES ('ユーザー3', 'user3@example.com');

-- 速い方法:1回で3件実行
INSERT INTO users (name, email)
VALUES
    ('ユーザー1', 'user1@example.com'),
    ('ユーザー2', 'user2@example.com'),
    ('ユーザー3', 'user3@example.com');

AUTO_INCREMENTの扱い方

AUTO_INCREMENTとは

AUTO_INCREMENTは、自動で1、2、3…と番号を振る機能です。主にIDカラムで使われます。

AUTO_INCREMENTカラムは省略できる

-- idを省略(自動で番号が振られる)
INSERT INTO users (name, email, age) VALUES ('田中太郎', 'tanaka@example.com', 25);

明示的に値を指定することも可能

-- idを明示的に指定
INSERT INTO users (id, name, email, age) VALUES (100, '特別ユーザー', 'special@example.com', 40);

AUTO_INCREMENTの動作例

初期状態(空のテーブル)

INSERT INTO users (name, email) VALUES ('ユーザー1', 'user1@example.com');
-- → id = 1

INSERT INTO users (name, email) VALUES ('ユーザー2', 'user2@example.com');
-- → id = 2

INSERT INTO users (id, name, email) VALUES (10, 'ユーザー3', 'user3@example.com');
-- → id = 10(明示的に指定)

INSERT INTO users (name, email) VALUES ('ユーザー4', 'user4@example.com');
-- → id = 11(10の次から自動採番が再開)

さまざまなデータ型の入れ方

文字列データ

INSERT INTO users (name, email) VALUES ('田中太郎', 'tanaka@example.com');

数値データ

INSERT INTO products (name, price, stock) VALUES ('商品A', 1500, 100);

日付・時刻データ

INSERT INTO posts (title, content, created_at) 
VALUES ('記事タイトル', '記事の内容です', '2025-06-03 14:30:00');

-- 現在時刻を入れる場合
INSERT INTO posts (title, content, created_at) 
VALUES ('記事タイトル', '記事の内容です', NOW());

真偽値(BOOLEAN)データ

INSERT INTO users (name, email, is_active) 
VALUES ('田中太郎', 'tanaka@example.com', TRUE);

-- 0と1でも指定可能
INSERT INTO users (name, email, is_active) 
VALUES ('佐藤花子', 'sato@example.com', 1);

NULLデータ

-- ageにNULLを入れる
INSERT INTO users (name, email, age) VALUES ('山田次郎', 'yamada@example.com', NULL);

-- カラムを省略してもNULLになる(制約による)
INSERT INTO users (name, email) VALUES ('鈴木一郎', 'suzuki@example.com');

JSON データ(MySQL 5.7以降)

INSERT INTO user_settings (user_id, preferences) 
VALUES (1, '{"theme": "dark", "language": "ja"}');

よくあるINSERTエラーと解決策

1. カラム数と値の数が合わない

エラー例

INSERT INTO users (name, email, age) VALUES ('田中太郎', 'tanaka@example.com');

エラーメッセージ

ERROR 1136 (21S01): Column count doesn't match value count at row 1

解決策

-- 全ての値を指定
INSERT INTO users (name, email, age) VALUES ('田中太郎', 'tanaka@example.com', 25);

-- または必要なカラムだけ指定
INSERT INTO users (name, email) VALUES ('田中太郎', 'tanaka@example.com');

2. 一意性制約違反(UNIQUE制約)

エラー例

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

-- 2回目はエラー(同じメールアドレス)
INSERT INTO users (name, email) VALUES ('田中次郎', 'tanaka@example.com');

エラーメッセージ

ERROR 1062 (23000): Duplicate entry 'tanaka@example.com' for key 'email'

解決策

-- 違うメールアドレスを使用
INSERT INTO users (name, email) VALUES ('田中次郎', 'tanaka2@example.com');

-- または事前にチェック
SELECT * FROM users WHERE email = 'tanaka@example.com';

3. NOT NULL制約違反

エラー例

INSERT INTO users (email, age) VALUES ('test@example.com', 25);
-- nameカラムがNOT NULLの場合エラー

エラーメッセージ

ERROR 1364 (HY000): Field 'name' doesn't have a default value

解決策

-- 必須カラムに値を指定
INSERT INTO users (name, email, age) VALUES ('田中太郎', 'test@example.com', 25);

4. データ型不整合

エラー例

INSERT INTO users (name, email, age) VALUES ('田中太郎', 'tanaka@example.com', 'twenty-five');
-- age は INT型なのに文字列を指定

エラーメッセージ

ERROR 1366 (HY000): Incorrect integer value: 'twenty-five' for column 'age' at row 1

解決策

-- 適切なデータ型で指定
INSERT INTO users (name, email, age) VALUES ('田中太郎', 'tanaka@example.com', 25);

5. 存在しないカラム名

エラー例

INSERT INTO users (name, emial, age) VALUES ('田中太郎', 'tanaka@example.com', 25);
-- email を emial と誤記

エラーメッセージ

ERROR 1054 (42S22): Unknown column 'emial' in 'field list'

解決策

-- 正しいカラム名を使用
INSERT INTO users (name, email, age) VALUES ('田中太郎', 'tanaka@example.com', 25);

実際の業務でよく使うINSERTパターン

ユーザー登録

INSERT INTO users (username, email, password_hash, full_name, created_at)
VALUES 
    ('tanaka123', 'tanaka@example.com', 'hashed_password_123', '田中太郎', NOW()),
    ('sato456', 'sato@example.com', 'hashed_password_456', '佐藤花子', NOW());

商品登録

INSERT INTO products (name, description, price, category_id, stock_quantity, is_active)
VALUES 
    ('ノートパソコン', 'Windows 11搭載の高性能ノートPC', 89800, 1, 50, TRUE),
    ('ワイヤレスマウス', 'Bluetooth対応の軽量マウス', 2980, 2, 200, TRUE);

注文データの登録

INSERT INTO orders (customer_id, order_date, total_amount, status)
VALUES (123, NOW(), 92780, 'pending');

-- 注文明細も一緒に登録
INSERT INTO order_items (order_id, product_id, quantity, unit_price)
VALUES 
    (LAST_INSERT_ID(), 1, 1, 89800),
    (LAST_INSERT_ID(), 2, 1, 2980);

ログデータの登録

INSERT INTO access_logs (user_id, action, ip_address, user_agent, timestamp)
VALUES (456, 'login', '192.168.1.100', 'Mozilla/5.0...', NOW());

設定データの登録

INSERT INTO user_settings (user_id, setting_key, setting_value)
VALUES 
    (123, 'theme', 'dark'),
    (123, 'language', 'ja'),
    (123, 'notification_email', 'true');

INSERT文の応用テクニック

INSERT … SELECT で他のテーブルからデータをコピー

基本的な使い方

INSERT INTO new_users (name, email)
SELECT name, email FROM old_users WHERE created_at >= '2025-01-01';

条件付きでのデータコピー

-- アクティブなユーザーのみをコピー
INSERT INTO active_users (user_id, name, email, last_login)
SELECT id, name, email, last_login_at
FROM users 
WHERE is_active = TRUE AND last_login_at >= '2025-01-01';

集計結果を新しいテーブルに保存

INSERT INTO monthly_sales_summary (year_month, total_amount, order_count)
SELECT 
    DATE_FORMAT(order_date, '%Y-%m') as year_month,
    SUM(total_amount) as total_amount,
    COUNT(*) as order_count
FROM orders 
WHERE order_date >= '2025-01-01'
GROUP BY DATE_FORMAT(order_date, '%Y-%m');

ON DUPLICATE KEY UPDATE で重複時の動作を制御

INSERT INTO user_stats (user_id, login_count, last_login)
VALUES (123, 1, NOW())
ON DUPLICATE KEY UPDATE 
    login_count = login_count + 1,
    last_login = NOW();

この例では:

  • user_id=123が初回の場合:新規レコード作成
  • user_id=123が既存の場合:login_countを+1、last_loginを更新

REPLACE INTO による上書きINSERT

REPLACE INTO user_preferences (user_id, setting_name, setting_value)
VALUES (123, 'theme', 'light');

REPLACE INTO は:

  • レコードが存在しない場合:INSERT
  • レコードが存在する場合:DELETE してから INSERT

INSERT IGNORE でエラーを無視

INSERT IGNORE INTO users (name, email)
VALUES 
    ('田中太郎', 'tanaka@example.com'),
    ('佐藤花子', 'duplicate@example.com'),  -- 重複エラーでも処理続行
    ('山田次郎', 'yamada@example.com');

パフォーマンスを考慮した INSERT

大量データのINSERT

一括INSERT の最適化

-- 1000件程度ずつに分けて実行
INSERT INTO large_table (col1, col2, col3)
VALUES 
    ('data1', 'value1', 123),
    ('data2', 'value2', 456),
    -- ... 1000件程度
    ('data1000', 'value1000', 789);

トランザクションを使用

START TRANSACTION;

INSERT INTO products (name, price) VALUES ('商品1', 100);
INSERT INTO products (name, price) VALUES ('商品2', 200);
INSERT INTO products (name, price) VALUES ('商品3', 300);

COMMIT;  -- 全て成功した場合のみ確定

インデックスを考慮したINSERT

-- 主キーの順番でINSERTすると効率的
INSERT INTO users (id, name, email) 
VALUES 
    (1, 'ユーザー1', 'user1@example.com'),
    (2, 'ユーザー2', 'user2@example.com'),
    (3, 'ユーザー3', 'user3@example.com');

安全なINSERTのための注意点

SQLインジェクション対策

危険な例(プログラムでの動的SQL生成)

-- ❌ 危険:ユーザー入力をそのまま埋め込み
$sql = "INSERT INTO users (name) VALUES ('" . $_POST['name'] . "')";

安全な例(プリペアドステートメント使用)

// ✅ 安全:プリペアドステートメント
$stmt = $pdo->prepare("INSERT INTO users (name, email) VALUES (?, ?)");
$stmt->execute([$name, $email]);

データの検証

-- 年齢の範囲チェック
INSERT INTO users (name, age) 
VALUES ('田中太郎', 25)
WHERE 25 BETWEEN 0 AND 150;  -- 実際にはアプリケーション側で検証

-- メールアドレスの形式チェック(アプリケーション側で実装)

トランザクション管理

START TRANSACTION;

INSERT INTO orders (customer_id, total_amount) VALUES (123, 5000);
SET @order_id = LAST_INSERT_ID();

INSERT INTO order_items (order_id, product_id, quantity) VALUES (@order_id, 1, 2);
INSERT INTO order_items (order_id, product_id, quantity) VALUES (@order_id, 2, 1);

-- エラーがあった場合はROLLBACK、成功した場合はCOMMIT
COMMIT;

デバッグとトラブルシューティング

INSERTの動作確認

1. テーブル構造の確認

DESCRIBE users;
-- または
SHOW CREATE TABLE users;

2. 制約の確認

SHOW CREATE TABLE users;

3. データの確認

-- INSERT後にデータを確認
SELECT * FROM users ORDER BY id DESC LIMIT 5;

よくある問題と解決法

問題1:文字化け

-- 文字エンコーディングを確認
SHOW VARIABLES LIKE 'character_set%';

-- UTF-8に設定
SET NAMES utf8mb4;

問題2:タイムゾーンの問題

-- タイムゾーンの確認
SELECT @@time_zone;

-- 日本時間に設定
SET time_zone = '+09:00';

問題3:権限エラー

-- 権限の確認
SHOW GRANTS FOR CURRENT_USER();

まとめ

MySQLのINSERT文は、データベースにデータを追加するための基本的で重要な操作です。

重要なポイント

  • 基本構文INSERT INTO テーブル名 (カラム名) VALUES (値)
  • 複数行INSERT:効率とパフォーマンスの向上
  • AUTO_INCREMENT:自動採番カラムは省略可能
  • 制約の理解:NOT NULL、UNIQUE、PRIMARY KEYなど
  • エラー対処:適切なエラーメッセージの読み方

ベストプラクティス

  • カラム名は明示的に指定する
  • 複数行INSERTを活用する
  • 適切なデータ型で値を指定する
  • エラーハンドリングを適切に行う
  • セキュリティを意識した実装にする

コメント

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