SQLを使用するうえで最も基本的な操作の1つが、テーブルにデータを追加するというものです。そんなとき、SQLでは「INSERT文」という文を含むクエリを実行します。
これによって、データを一つ一つ登録したり、他のテーブルから複数のデータをまとめて持ってきたりといったことが可能になります。
本記事では、INSERT文の基本的な使い方からCASE式やJOIN句との併用方法を中心に解説します。
基礎の基礎から応用例まで詳しく解説していきますので、ぜひ参考にしてください!
※本記事ではMySQLでの仕様をもとに検証・解説しています。
INSERT文とは
SQLのINSERT文とは、データベースのテーブルに新しいレコードを挿入(insert)するクエリです。挿入するデータの内容としては固定値のほか、別のテーブルから引っ張ってきたデータや、CASE式で分岐処理を行った値、JOIN句でテーブル結合した結果など、さまざまな値をテーブルに挿入することができます。
【基本構文】
INSERT文の基本的な構文は、データを挿入するテーブルを指定し、続けて各カラム名とそれに対応するデータの値を指定します。
INSERT INTO テーブル名 (カラム1, カラム2, ...)
VALUES (値1, 値2, ...);
テーブル名のあとに、括弧で囲んでカラム1, カラム2…とカラム名をカンマで区切って並べます。そして、VALUESのあとの括弧には各カラムに登録する値を同様に並べます。なお、この際カラム名と値のカラム数を一致させる必要があります。
INSERT文の使い方
INSERT文の具体的な使い方を解説していくにあたって、サンプルとして「テスト(test)」テーブルを用意しました。
「テスト(test)」テーブル
ID(id) | 氏名(name) | 性別(gender) | 点数(point) |
1001 | 秋山 | 男 | 80 |
1002 | 久保田 | 女 | 100 |
1003 | 佐々木 | 女 | 65 |
1004 | 佐藤 | 男 | 75 |
単一レコードの追加
ここに、新たに鈴木さんのレコードを追加します。この場合、以下のようなINSERT文になります。
【実行クエリ】
INSERT INTO test (id,name,gender,point)
VALUES (1005,'鈴木','女',60);
【実行結果】
ID(id) | 氏名(name) | 性別(gender) | 点数(point) |
1001 | 秋山 | 男 | 80 |
1002 | 久保田 | 女 | 100 |
1003 | 佐々木 | 女 | 65 |
1004 | 佐藤 | 男 | 75 |
1005 | 鈴木 | 女 | 60 |
鈴木さんのレコードが追加されました。
複数のレコードを一度に追加
一つのSQL文で、複数のレコードをテーブルに追加することもできます。
【実行クエリ】
INSERT INTO test (id,name,gender,point)
VALUES (1006,'田中','男',90),(1007,'土屋','女',55);
【実行結果】
ID(id) | 氏名(name) | 性別(gender) | 点数(point) |
1001 | 秋山 | 男 | 80 |
1002 | 久保田 | 女 | 100 |
1003 | 佐々木 | 女 | 65 |
1004 | 佐藤 | 男 | 75 |
1005 | 鈴木 | 女 | 60 |
1006 | 田中 | 男 | 90 |
1007 | 土屋 | 女 | 55 |
田中さんと土屋さんのレコードが追加されました。
カラム名は省略可能
次のように、カラム名は省略することもできます。
【実行クエリ】
INSERT INTO test
VALUES (1005,'鈴木','女',60);
この場合、値を記述する順序がテーブルのカラムと一致している必要があります。
ただし、テーブルの構造が変わった場合やカラムの順序を間違えた場合はデータを正しく挿入できないケースがあります。そのため、INSERTを行う場合はカラム名を明示することが推奨されています。
INSERTするデータを別のテーブルから取得する
INSERT文では、挿入する値を直接入力しますが、サブクエリ(副問合せ)としてSELECT句を使用することで、別のテーブルから取得したデータをテーブルに挿入することができます。
例として、先ほどのテスト(test)テーブルから、点数(point)が60点未満の生徒のレコードを新しいテーブル「再テスト(retest)」テーブルに追加します。
「テスト(test)」テーブル
ID(id) | 氏名(name) | 性別(gender) | 点数(point) |
1001 | 秋山 | 男 | 80 |
1002 | 久保田 | 女 | 100 |
1003 | 佐々木 | 女 | 65 |
1004 | 佐藤 | 男 | 75 |
1005 | 鈴木 | 女 | 60 |
1006 | 田中 | 男 | 90 |
1007 | 土屋 | 女 | 55 |
【実行クエリ】
INSERT INTO retest (id,name,gender,point)
SELECT id,name,gender,point
FROM test
WHERE point < 60;
クエリ内の WHERE句で「WHERE point < 60」という条件を設定しています。この指定によって、testテーブルからpointカラムの値が60点未満に該当するレコードのみが抽出されます。
WHERE句は、特定の条件下でのデータの絞り込みに使用されます。詳しくは、当ブログの【SQL入門1】WHEREで検索条件を指定する方法を解説で、WHEREの基本を詳しく解説しています。ぜひ参考にしてください。
【実行結果】
ID(id) | 氏名(name) | 性別(gender) | 点数(point) |
1007 | 土屋 | 女 | 55 |
60点未満の生徒のデータだけが抽出され、新しいテーブルに登録されました。
DEFAULT値を使ったINSERT文
DEFAULT値とは、データベーステーブルの設計時に、各カラムに予め設定できるデフォルト値を指します。この値は、INSERT文で該当のカラムに明示的な値が提供されなかった場合に使用されます。これにより、すべてのデータを都度入力することなく、デフォルト値でデータを挿入できます。
テスト(test)テーブルで、点数(point)カラムのデフォルト値を「-」として設定します。
【実行クエリ】
CREATE TABLE test(
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
gender VARCHAR(10) DEFAULT -,
point INT NOT NULL
);
上記のテーブル定義の「gender VARCHAR(10) DEFAULT -」部分があることで、性別(gender)カラムに特定の値を指定しない場合、「-」と自動で挿入されるようになります。
次に、新しい生徒のデータを挿入しますが、性別(gender)は指定せず、デフォルトの値を使用します。
【実行クエリ】
INSERT INTO test (id,name,point)
VALUES (1008,'野村',70);
上記のINSERT文では、性別(gender)についての指定がないため、デフォルトの値である「-」が表示されます。
【実行結果】
ID(id) | 氏名(name) | 性別(gender) | 点数(point) |
1001 | 秋山 | 男 | 80 |
1002 | 久保田 | 女 | 100 |
1003 | 佐々木 | 女 | 65 |
1004 | 佐藤 | 男 | 75 |
1005 | 鈴木 | 女 | 60 |
1006 | 田中 | 男 | 90 |
1007 | 土屋 | 女 | 55 |
1008 | 野村 | – | 70 |
CASE式との併用
CASE式は条件分岐処理を行うクエリで、データごとに指定条件にあてはまるかを判定し、判定結果に応じて異なる処理を行います。INSERT文は、「CASE式」と併用することでCASE式で返された値を挿入できます。
「テスト(test)」テーブル
ID(id) | 氏名(name) | 性別(gender) | 点数(point) |
1001 | 秋山 | 男 | 80 |
1002 | 久保田 | 女 | 100 |
1003 | 佐々木 | 女 | 65 |
1004 | 佐藤 | 男 | 75 |
1005 | 鈴木 | 女 | 60 |
1006 | 田中 | 男 | 90 |
1007 | 土屋 | 女 | 55 |
下記のコードはテストの点数ごとに成績を付けています。
【テーブル作成用クエリ】
CREATE TABLE grades(
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
point INT NOT NULL,
grade VARCHAR(10),
);
【実行クエリ】
INSERT INTO grades(id,name,point,grade)
VALUES(
SELECT name,point,
CASE point
WHEN point >= 90 THEN '秀'
WHEN point >= 80 THEN '優'
WHEN point >= 70 THEN '良'
WHEN point >= 60 THEN '可'
ELSE 不可
END AS grade
FROM test
);
【実行結果】
ID(id) | 氏名(name) | 点数(point) | 成績(grade) |
1001 | 秋山 | 80 | 優 |
1002 | 久保田 | 100 | 秀 |
1003 | 佐々木 | NULL | 不可 |
1004 | 佐藤 | 75 | 良 |
1005 | 鈴木 | 60 | 可 |
1006 | 田中 | 90 | 秀 |
1007 | 土屋 | 55 | 不可 |
テーブル結合した結果をINSERTする
INSERT文は、JOIN句でテーブル結合させた結果をINSERTすることも可能です。
説明にあたって新たに以下のテーブルを使用します。
「生徒(student)」テーブル
学籍番号(number) | 氏名(name) | 部活ID(club_id) |
1 | 菊池 | 1 |
2 | 鈴木 | 3 |
3 | 田中 | 4 |
4 | 山田 | 1 |
「運動部(sport_club)」テーブル
ID(id) | 競技(sport) |
1 | 野球 |
2 | サッカー |
3 | バスケットボール |
「生徒」テーブルの「部活」カラムと「運動部」テーブルの「ID」カラムを紐づけ、結合条件を満たす場合に、「生徒」テーブルの「氏名」カラムと「運動部」テーブルの「競技」カラムを表示します。
【実行クエリ】
SELECT student.name,sport_club.sport FROM student JOIN sport_club ON student.club_id = sport_club.id;
【実行結果】
氏名 (name) | 競技 (sport) |
菊池 | 野球 |
鈴木 | バスケットボール |
山田 | 野球 |
共通する値がない「生徒」テーブルの田中さん、「運動部」テーブルの「サッカー」が表示されていません。
これとINSERT文を併用します。新たなテーブル「運動部所属者(sport_student)」テーブルに運動部に属する生徒のデータを挿入します。
【実行クエリ】
INSERT INTO sport_student (name,sport)
SELECT student.name,sport_club.sport FROM student JOIN sport_club ON student.club_id = sport_club.id;
【実行結果】
氏名 (name) | 競技 (sport) |
菊池 | 野球 |
鈴木 | バスケットボール |
山田 | 野球 |
INSERT文のカッコ内とSELECT句内の抽出カラムが対応しているのが分かります。
大量のレコードを追加したいときはどうする?
INSERT文で追加するレコードが1つだったり、複数レコードでも数が多くない場合は、追加するレコードごとにINSERT文を書いても問題はありません。
ですが、一度に大量のレコードを追加したいとなったときに、一つ一つINSERT文を書くのはSQLを書く人にとっても処理が実行されるDBにとっても効率が悪く、実行速度が大幅に下がったり大きな負荷がかかったりする原因となってしまいます。
そこで、効率的にクエリを記述し、DBの処理に大きな負荷をかけずに実行するためのテクニックとして「バルクインサート」(Bulk Insert)というものがあります。
一度に複数のレコードを追加する「バルクインサート」
「バルクインサート」(Bulk Insert)とは、一度あるいは少ない回数のINSERT文の実行で大量のレコードを効率的に挿入する手法です。「バルク(bulk)」とは「ひとつにまとまったもの」を意味しています。
バルクインサートのメリット
バルクインサートを利用することで、少ない回数の操作で大量のデータをDBに追加することができます。これにはいくつかのメリットがあります。
メリット1: 高速なクエリ実行
大量のデータを追加するときに、いちいちINSERT文を実行していたのではそのぶん処理の負荷がかかり、実行速度が大幅に低下する原因になります。対してバルクインサートを使用すれば、より効率的かつ高速にデータを追加することが可能になります。
メリット2: トランザクションの最適化
SQLには実行される一連のデータ更新処理をひとまとまりの単位として扱い、その操作が全て成功したら状態を更新し、失敗したら一連の操作で変更されたものを元に戻すといった仕組みがあり、そのひとまとまりになったデータ更新処理の単位をトランザクションと言います。
バルクインサートによってデータを更新すると、大量のデータ追加の処理が一つのトランザクションとして扱われることになり、更新が失敗したときに一部のデータだけが入るというようなエラーを防ぐことができるようになります。そのため、INSERT文の1つ1つがトランザクションとして扱われる場合と比べて、より安全かつ確実にデータベースの更新を行えるようになります。
メリット3: ディスクI/Oの最適化
バルクインサートには専用の構文やメソッドが用意されていることが多く、それらの方法でバルクインサートを行った場合は、通常のINSERTを同じレコード分だけ繰り返した場合と比べて、データベースのディスクI/O(入出力)やメモリバッファへの書き込みなどが最適化されるように専用の内部処理が行われるようになります。これにより、単に高速なだけでなくハードウェアへの負担が少ない形で実行できるという利点があります。
まとめ
私たちが日々行うデータの操作の中でも、INSERT文はよく利用される命令の一つです。本記事で紹介した知識を活用して、日々のデータベース作業を効率良く進めていきましょう。
以下では、SQLに関するさまざまな記事を取り上げています。SQLに関する疑問や興味がある方は、ぜひ併せて参考にしてみてください。
SQL関連記事
- RDBを操作するデータベース言語「SQL」とは?
- RDB以外のデータベース管理システム「NoSQL」とは?
- RDB管理システム「MySQL」とは?
- RDB管理システム「PostgreSQL」とは?
- RDB管理システム「SQL Server」とは?
- RDB管理システム「SQLite」とは?
- ブラウザ上でMySQLを管理できる「phpMyAdmin」とは?
- データを抽出する「SELECT」文
- データを追加する「INSERT」文
- データを削除する「DELETE」文
- データを更新する「UPDATE」文
- テーブル構造を変更する「ALTER TABLE」文
- 抽出条件を指定する「WHERE」句
- 抽出条件を指定する「HAVING」句
- 複数の抽出条件をまとめる「IN」句
- 重複レコードを除外する「DISTINCT」
- 抽出範囲を指定する「BETWEEN」演算子
- 抽出条件を満たすレコードの存在の有無を調べる「EXISTS」句
- レコード件数を取得する集計関数「COUNT」関数
- レコードをグループ化する「GROUP BY」句
- 抽出結果を並び替える「ORDER BY」句
- テーブル間のデータを結合する「JOIN」句
- 内部結合「INNER JOIN」句
- 抽出結果を統合して表示する「UNION」句
- データの曖昧検索「LIKE」句
- データの取得件数を制限する「LIMIT」句
- 条件分岐処理「CASE」式
- 「NULL」の扱い方
- 「主キー」とは?
- 「外部キー」とは?
SQLの勉強方法は?
書籍やインターネットで学習する方法があります。昨今では、YouTubeなどの動画サイトやエンジニアのコミュニティサイトなども充実していて多くの情報が手に入ります。
そして、より効率的に知識・スキルを習得するには、知識をつけながら実際に手を動かしてみるなど、インプットとアウトプットを繰り返していくことが重要です。特に独学の場合は、有識者に質問ができたりフィードバックをもらえるような環境があると、理解度が深まるでしょう。
ただ、SQLに限らず、ITスキルを身につける際、どうしても課題にぶつかってしまうことはありますよね。特に独学だと、わからない部分をプロに質問できる機会を確保しにくく、モチベーションが続きにくいという側面があります。独学でモチベーションを維持する自信がない人にはプログラミングスクールという手もあります。費用は掛かりますが、その分スキルを身につけやすいです。しっかりと知識・スキルを習得して実践に活かしたいという人はプログラミングスクールがおすすめです。
プログラミングスクールならテックマニアがおすすめ!

ITスキル需要の高まりとともにプログラミングスクールも増えました。しかし、どのスクールに通うべきか迷ってしまう人もいるでしょう。そんな方にはテックマニアをおすすめします!これまで多くのITエンジニアを育成・輩出してきたテックマニアでもプログラミングスクールを開講しています。
<テックマニアの特徴>
・たしかな育成実績と親身な教育 ~セカンドキャリアを全力支援~
・講師が現役エンジニア ~“本当”の開発ノウハウを直に学べる~
・専属講師が学習を徹底サポート ~「わからない」を徹底解決~
・実務ベースでスキルを習得 ~実践的な凝縮カリキュラム~
このような特徴を持つテックマニアはITエンジニアのスタートラインとして最適です。
話を聞きたい・詳しく知りたいという方はこちらからお気軽にお問い合わせください。