SQLを使用するうえで最も基本的な操作の1つが、テーブルにデータを追加するというものです。そんなとき、SQLでは「INSERT文」という文を含むクエリを実行します。
これによって、データを一つ一つ登録したり、他のテーブルから複数のデータをまとめて持ってきたりといったことが可能になります。
本記事では、INSERT文の基本的な使い方やよくあるエラーの対処法から、CASE式やJOIN句との併用方法までを解説します。
INSERT文とは
SQLのINSERT文とは、データベースのテーブルに新しいレコードを挿入(insert)するクエリです。挿入するデータの内容としては固定値のほか、別のテーブルから引っ張ってきたデータや、CASE式で分岐処理を行った値、JOIN句でテーブル結合した結果など、さまざまな値をテーブルに挿入することができます。
INSERT文は、SELECT(取得)・UPDATE(更新)・DELETE(削除)と並ぶ、テーブルの中身を操作するための基本的なSQL文の1つです。
【基本構文】
INSERT文の基本的な構文は、データを挿入するテーブルを指定し、続けて各カラム名とそれに対応するデータの値を指定します。
INSERT INTO テーブル名 (カラム1, カラム2, ...)
VALUES (値1, 値2, ...);INSERT文で指定するのは「どのテーブルに」「どのカラムに」「どんな値を」の3つです。テーブル名のあとの括弧にカラム名をカンマで区切って並べ、VALUESのあとの括弧に、各カラムに登録する値を同じ順番で並べます。1番目のカラムには1番目の値、2番目のカラムには2番目の値が入るため、カラムと値は数・順番・型をそろえる必要があります。構文の詳細は、MySQL公式リファレンスマニュアルのINSERTステートメントで確認できます。
また、値のうち文字列や日付は「’鈴木’」「’2026-10-01’」のようにシングルクォート(’)で囲み、数値は「60」のようにそのまま書きます。文字列の中にシングルクォートを含めたい場合は、「’I”m’」のように2つ続けて書きます。詳しいルールはMySQL公式リファレンスの文字列リテラルのページにまとめられています。
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 |
鈴木さんのレコードが追加されました。
mysqlコマンドラインツールで実行した場合は、画面に「Query OK, 1 row affected」のように、INSERT文で追加された行数が表示されます。思ったとおりの件数が追加されたかを確認する目安になります。
複数のレコードを一度に追加
一つの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 |
田中さんと土屋さんのレコードが追加されました。
VALUESのあとに「(値1, 値2, …)」の組をカンマで区切って並べると、1組が1レコードになります。mysqlコマンドラインツールでは、次のように追加された件数が表示されます。
Query OK, 2 rows affected
Records: 2 Duplicates: 0 Warnings: 0「Records」は処理されたレコードの数、「Warnings」は警告の数です。
カラム名は省略可能
カラム名は省略することもできます。先ほどの鈴木さんを追加するINSERT文を、カラム名を省略して書くと次のようになります。
【実行クエリ】
INSERT INTO test
VALUES (1005,'鈴木','女',60);この場合、値を記述する順序がテーブルのカラムと一致している必要があります。また、テーブルのすべてのカラムの値を書かなければならず、一部のカラムだけを指定することはできません。
ただし、テーブルの構造が変わった場合やカラムの順序を間違えた場合はデータを正しく挿入できないケースがあります。そのため、INSERTを行う場合はカラム名を明示することが推奨されています。
なお、このクエリは「単一レコードの追加」と同じデータを書き方を変えて示したものです。鈴木さんを追加したあとに続けて実行すると、ID(1005)が重複してエラーになります(詳しくは次の章で解説します)。
INSERT文でよくあるエラーと対処法
INSERT文を書き始めたばかりのころによく出るエラーと、その直し方を紹介します。エラーメッセージはMySQLのものです。エラー番号ごとの意味は、MySQL公式のサーバーエラーメッセージリファレンス(英語)で調べられます。
エラーの例で使うテスト(test)テーブルは、次のように作成しています。ID(id)は主キー(PRIMARY KEY)で、氏名(name)と点数(point)には必ず値が必要なNOT NULLを指定しています。
【テーブル作成用クエリ】
CREATE TABLE test(
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
gender VARCHAR(10) DEFAULT '-',
point INT NOT NULL
);AUTO_INCREMENTとDEFAULTについては、「DEFAULT値を使ったINSERT文」で解説します。
カラムと値の数が合っていない
INSERT INTOで指定したカラムの数と、VALUESに書いた値の数がずれているとエラーになります。次の例では、カラムを4つ指定しているのに値を3つしか書いていません。
【間違った例】
INSERT INTO test (id,name,gender,point)
VALUES (1005,'鈴木','女');
-- ERROR 1136 (21S01): Column count doesn't match value count at row 1「カラムの数と値の数が一致しない」という意味のエラーです。このエラーが出たら、カラム名と値を1つずつ見比べて、抜けている値や余分な値がないかを確認しましょう。カラム名を省略した場合は、テーブルのカラム数と値の数を比べます。
文字列を引用符で囲んでいない
文字列の値をシングルクォートで囲み忘れると、MySQLはその文字をカラム名として読み取ろうとするため、エラーになります。
【間違った例】
INSERT INTO test (id,name,gender,point)
VALUES (1005,鈴木,'女',60);
-- ERROR 1054 (42S22): Unknown column '鈴木' in 'field list'「鈴木というカラムが見つからない」という意味のエラーです。「’鈴木’」のようにシングルクォートで囲めば解決します。
NOT NULLのカラムに値を入れていない
NOT NULLを指定していて、デフォルト値もないカラムは、INSERT文で省略できません。テスト(test)テーブルでは氏名(name)と点数(point)が該当します。点数を省略すると、MySQLの初期設定(strictモードが有効な状態)では次のようにエラーになります。
【間違った例】
INSERT INTO test (id,name)
VALUES (1009,'森');
-- ERROR 1364 (HY000): Field 'point' doesn't have a default value「pointカラムにはデフォルト値がない」という意味のエラーです。NOT NULLのカラムには、INSERT文で必ず値を指定しましょう。NULLの意味や扱い方については、以下の記事で解説しています。
主キーの値が重複している
主キー(PRIMARY KEY)やUNIQUEを指定したカラムには、同じ値を2回入れられません。すでに秋山さんが使っているID(1001)で別の生徒を追加しようとすると、次のエラーになります。
【間違った例】
INSERT INTO test (id,name,gender,point)
VALUES (1001,'山本','男',70);
-- ERROR 1062 (23000): Duplicate entry '1001' for key 'test.PRIMARY'「1001という値がすでに主キーに存在する」という意味のエラーです(MySQL 8.0.19より前のバージョンでは「for key ‘PRIMARY’」と表示されます)。新しいレコードを追加したいなら、使われていないIDを指定しましょう。IDを自動で振る方法は「IDを自動で連番にして追加する」で解説しています。主キーについては、以下の記事で詳しく解説しています。
重複したときに更新・無視したい場合
「同じIDがなければ追加し、あれば上書きしたい」という場合は、MySQLでは「ON DUPLICATE KEY UPDATE」を使います。このように追加と更新をまとめて行う処理は、UPSERT(アップサート)とも呼ばれます。
【実行クエリ】
INSERT INTO test (id,name,gender,point)
VALUES (1001,'秋山','男',85) AS new
ON DUPLICATE KEY UPDATE point = new.point;【実行結果】
| ID(id) | 氏名(name) | 性別(gender) | 点数(point) |
| 1001 | 秋山 | 男 | 85 |
※ID 1001の行のみ表示しています。
ID 1001はすでにあるため新しい行は追加されず、「ON DUPLICATE KEY UPDATE」のあとに書いた内容で秋山さんの点数が80点から85点に更新されました。「AS new」は追加しようとした行に付けた名前で、「new.point」はその行の点数(85)を指します。IDが存在しなかった場合は、通常のINSERTと同じように新しい行が追加されます。
「AS new」の書き方はMySQL 8.0.19から使えます(MySQL公式リファレンスのON DUPLICATE KEY UPDATEのページ)。古い記事では「point = VALUES(point)」という書き方がよく紹介されていますが、この書き方はMySQL 8.0.20以降は非推奨です。
重複した行を更新せずに無視したいだけなら、「INSERT IGNORE INTO ~」と書きます。重複する行はエラーにならずに追加されず、代わりに警告が記録されます。ただし、重複以外のエラーも警告として扱われて見落としやすくなるため、使う場面は限定しましょう。
なお、これらはMySQLの構文です。PostgreSQLでは「ON CONFLICT」という別の構文を使います(PostgreSQL公式ドキュメントのINSERTのページ、英語)。
※以降の章では、秋山さんの点数を元の80点のまま説明します。
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文はデータを追加するだけで、テーブルそのものは作りません。そのため、追加先の再テスト(retest)テーブルはあらかじめ作成しておきます。
【テーブル作成用クエリ】
CREATE TABLE retest(
id INT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
gender VARCHAR(10),
point INT NOT NULL
);【実行クエリ】
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句は、特定の条件下でのデータの絞り込みに使用されます。WHEREの基本は、以下の記事で詳しく解説しています。
【実行結果】
| ID(id) | 氏名(name) | 性別(gender) | 点数(point) |
| 1007 | 土屋 | 女 | 55 |
60点未満の生徒のデータだけが抽出され、新しいテーブルに登録されました。
この書き方ではVALUESは使わず、INSERT INTOのあとにそのままSELECT文を続けます。INSERT INTOで指定したカラムには、SELECTで取得したカラムが左から順番に入るため、ここでもカラムの数と順番を合わせておきましょう。この書き方はMySQL公式リファレンスのINSERT … SELECTのページでも解説されています。
また、mysqlコマンドラインツールでは「Records: 1 Duplicates: 0 Warnings: 0」のように追加された件数が表示されます。SELECT文の条件しだいで追加される件数が変わるので、想定どおりの件数になっているかを確認しておくと安心です。
DEFAULT値を使ったINSERT文
DEFAULT値とは、データベーステーブルの設計時に、各カラムに予め設定できるデフォルト値を指します。この値は、INSERT文で該当のカラムに明示的な値が提供されなかった場合に使用されます。これにより、すべてのデータを都度入力することなく、デフォルト値でデータを挿入できます。
「INSERT文でよくあるエラーと対処法」で紹介したテスト(test)テーブルでは、性別(gender)カラムのデフォルト値を「-」に設定しています。
【テーブル作成用クエリ(再掲)】
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 |
INSERT文で省略したカラムに入る値は、カラムの定義によって次のように変わります(詳しくはMySQL公式リファレンスのデータ型デフォルト値のページを参照)。
| カラムの定義 | 省略したときに入る値 |
| DEFAULT値を設定している | 設定したデフォルト値 |
| DEFAULT値がなく、NULLを許可している | NULL |
| DEFAULT値がなく、NOT NULLを指定している | 省略できない(エラー) |
今回のテーブルでは、氏名(name)と点数(point)にNOT NULLを指定しているため、この2つは省略できません(エラーの例は「NOT NULLのカラムに値を入れていない」で紹介しています)。反対に、NULLを許可しているカラムであれば値を省略しておき、あとからUPDATE文で値を入れることもできます。UPDATE文の使い方は、以下の記事で解説しています。
IDを自動で連番にして追加する
上記のテーブル定義では、ID(id)カラムに「AUTO_INCREMENT」を指定しています。AUTO_INCREMENTを指定したカラムは、INSERT文で値を省略すると、MySQLが自動で連番を振ってくれます。
【実行クエリ】
INSERT INTO test (name,gender,point)
VALUES ('森','男',85);【実行結果】
| ID(id) | 氏名(name) | 性別(gender) | 点数(point) |
| 1007 | 土屋 | 女 | 55 |
| 1008 | 野村 | – | 70 |
| 1009 | 森 | 男 | 85 |
※1006以前のレコードは省略しています。
IDを指定していませんが、それまでの最大値(1008)の次の値である1009が自動で入りました。AUTO_INCREMENTを設定したテーブルが空の状態から使い始めた場合は、1から順番に番号が振られます。また、「VALUES (NULL,’森’,’男’,85)」のようにIDにNULLを指定した場合も、同じように自動で番号が振られます。採番のルールはMySQL公式リファレンスのAUTO_INCREMENTの使用のページで確認できます。
新しいIDを「SELECT MAX(id) + 1」のように、今ある最大値に1を足して決める方法もありますが、おすすめできません。複数の人やプログラムが同時にデータを追加すると、同じIDを使おうとしてしまうおそれがあるためです。IDの採番はAUTO_INCREMENTに任せるのが基本です。
なお、直前のINSERT文で自動採番された値は「SELECT LAST_INSERT_ID();」で確認できます。追加したレコードのIDを、続けて別のテーブルに登録したいときなどに使います。
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)
SELECT id,name,point,
CASE
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 | 佐々木 | 65 | 可 |
| 1004 | 佐藤 | 75 | 良 |
| 1005 | 鈴木 | 60 | 可 |
| 1006 | 田中 | 90 | 秀 |
| 1007 | 土屋 | 55 | 不可 |
SELECT文で取得した「id」「name」「point」と、CASE式で判定した成績の4つが、INSERT INTOで指定した4つのカラムに順番どおりに入っています。
CASE式のWHENは上から順番に判定され、最初に条件を満たしたWHENの値が使われます。そのため、100点の久保田さんは「point >= 80」の条件も満たしていますが、先に判定される「point >= 90」に当てはまった時点で「秀」に決まります。どの条件にも当てはまらない場合は、ELSEの「不可」が入ります。
CASE式で「〇点以上」のような範囲の条件を書くときは、上のように「CASE」の直後には何も書かず、WHENのあとに条件を書きます。次のように「CASE point」と書く形(単純CASE式)は、値が等しいかどうかしか比べられないため、範囲の判定には使えません。
【間違った例】
-- 単純CASE式に範囲の条件を書いている
CASE point
WHEN point >= 90 THEN '秀'
WHEN point >= 80 THEN '優'
...この書き方は「pointの値」と「point >= 90の判定結果」が等しいかを比べることになるため、エラーにならなかったとしても意図した成績は付きません。単純CASE式は「WHEN 1 THEN ~」のように特定の値と一致するかを調べるときに使い、範囲や複数の条件を組み合わせる場合は上の書き方(検索CASE式)を使いましょう。
また、SELECT文で取得した複数のレコードをまとめてINSERTするときは、「VALUES( SELECT … )」のようにVALUESの中にSELECT文を入れるのではなく、INSERT INTOのあとにSELECT文を直接続けます。
CASE式の詳しい使い方は、以下の記事で解説しています。
テーブル結合した結果を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)」テーブルに運動部に属する生徒のデータを挿入します。先に、追加先のテーブルを作成しておきます。
【テーブル作成用クエリ】
CREATE TABLE sport_student(
name VARCHAR(50) NOT NULL,
sport VARCHAR(50) NOT NULL
);【実行クエリ】
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句内の抽出カラムが対応しているのが分かります。
JOIN(内部結合)では、結合条件に一致しない行は結果に含まれません。そのため、運動部に所属していない田中さんのレコードは追加されていません。結合相手がない生徒も含めてすべて追加したい場合は、LEFT JOIN(外部結合)を使います。結合の種類については、以下の記事で詳しく解説しています。
なお、別のテーブルから値を1つだけ取ってきたい場合は、VALUESの中にSELECT文(サブクエリ)を書く方法もあります。たとえば、新しい生徒を「生徒」テーブルに追加するときに、部活IDを番号ではなく競技名から調べて登録できます。
【実行クエリ】
INSERT INTO student (number,name,club_id)
VALUES (5,'高橋',(SELECT id FROM sport_club WHERE sport = 'サッカー'));【実行結果】
| 学籍番号(number) | 氏名(name) | 部活ID(club_id) |
| 1 | 菊池 | 1 |
| 2 | 鈴木 | 3 |
| 3 | 田中 | 4 |
| 4 | 山田 | 1 |
| 5 | 高橋 | 2 |
カッコ内のSELECT文で「サッカー」のIDである2が取得され、その値がclub_idに入りました。このようにVALUESの中で使うSELECT文は、1行1列(値1つ)を返すように書く必要があります。条件に当てはまる行が2行以上あると「ERROR 1242 (21000): Subquery returns more than 1 row」というエラーになり、1行も当てはまらない場合はサブクエリの結果がNULLになります。
生徒テーブルの部活IDのように、別のテーブルのIDを参照するカラムと外部キーの関係は、以下の記事で解説しています。
大量のレコードを追加したいときはどうする?
INSERT文で追加するレコードが1つだったり、複数レコードでも数が多くない場合は、追加するレコードごとにINSERT文を書いても問題はありません。
ですが、一度に大量のレコードを追加したいとなったときに、一つ一つINSERT文を書くのはSQLを書く人にとっても処理が実行されるDBにとっても効率が悪く、実行速度が大幅に下がったり大きな負荷がかかったりする原因となってしまいます。
そこで、効率的にクエリを記述し、DBの処理に大きな負荷をかけずに実行するためのテクニックとして「バルクインサート」(Bulk Insert)というものがあります。
一度に複数のレコードを追加する「バルクインサート」
「バルクインサート」(Bulk Insert)とは、一度あるいは少ない回数のINSERT文の実行で大量のレコードを効率的に挿入する手法です。「バルク(bulk)」とは「ひとつにまとまったもの」を意味しています。
MySQLで最も基本的なバルクインサートは、「複数のレコードを一度に追加」で紹介した、VALUESのあとに複数の組を並べる書き方です。MySQL公式ドキュメントのINSERTステートメントの最適化のページでも、1行ずつINSERT文を実行するよりかなり速くなる方法として紹介されています。
【1行ずつ追加する場合】
INSERT INTO test (id,name,gender,point) VALUES (1006,'田中','男',90);
INSERT INTO test (id,name,gender,point) VALUES (1007,'土屋','女',55);
INSERT INTO test (id,name,gender,point) VALUES (1008,'野村','-',70);【バルクインサートで追加する場合】
INSERT INTO test (id,name,gender,point)
VALUES (1006,'田中','男',90),
(1007,'土屋','女',55),
(1008,'野村','-',70);さらに件数が多く、INSERT文を何回かに分けて実行する場合は、自動コミット(1文ごとに変更を確定する機能)をオフにして、最後にまとめて確定する方法もあります(MySQL公式ドキュメントのInnoDBテーブルの一括データロードのページで紹介されている方法です)。
SET autocommit=0;
INSERT INTO test (id,name,gender,point) VALUES (...),(...),(...);
INSERT INTO test (id,name,gender,point) VALUES (...),(...),(...);
COMMIT;MySQLは初期設定ではINSERT文を実行するたびに変更を確定しますが、autocommitを0にすると、COMMITを実行するまで変更が確定しません。途中で間違いに気づいた場合は、COMMITの代わりにROLLBACKを実行すれば、追加をまとめて取り消せます。作業が終わったら「SET autocommit=1;」で元の設定に戻しておきましょう。
バルクインサートのメリット
バルクインサートを利用することで、少ない回数の操作で大量のデータをDBに追加することができます。これにはいくつかのメリットがあります。
メリット1: 高速なクエリ実行
大量のデータを追加するときに、いちいちINSERT文を実行していたのではそのぶん処理の負荷がかかり、実行速度が大幅に低下する原因になります。対してバルクインサートを使用すれば、より効率的かつ高速にデータを追加することが可能になります。
メリット2: トランザクションの最適化
SQLには実行される一連のデータ更新処理をひとまとまりの単位として扱い、その操作が全て成功したら状態を更新し、失敗したら一連の操作で変更されたものを元に戻すといった仕組みがあり、そのひとまとまりになったデータ更新処理の単位をトランザクションと言います。
バルクインサートによってデータを更新すると、大量のデータ追加の処理が一つのトランザクションとして扱われることになり、更新が失敗したときに一部のデータだけが入るというようなエラーを防ぐことができるようになります。そのため、INSERT文の1つ1つがトランザクションとして扱われる場合と比べて、より安全かつ確実にデータベースの更新を行えるようになります。
メリット3: ディスクI/Oの最適化
バルクインサートには専用の構文やメソッドが用意されていることが多く、それらの方法でバルクインサートを行った場合は、通常のINSERTを同じレコード分だけ繰り返した場合と比べて、データベースのディスクI/O(入出力)やメモリバッファへの書き込みなどが最適化されるように専用の内部処理が行われるようになります。これにより、単に高速なだけでなくハードウェアへの負担が少ない形で実行できるという利点があります。たとえばMySQLでは、テキストファイルからデータを読み込む「LOAD DATA」文が用意されており、公式ドキュメントでは通常のINSERT文より20倍ほど速いことが多いと説明されています。
まとめ
私たちが日々行うデータの操作の中でも、INSERT文はよく利用される命令の一つです。本記事のポイントは次のとおりです。
- INSERT文は「INSERT INTO テーブル名 (カラム) VALUES (値)」の形で書き、カラムと値の数・順番・型をそろえる
- 文字列や日付はシングルクォートで囲む
- VALUESのあとに複数の組を並べると、一度に複数のレコードを追加できる
- INSERT INTOのあとにSELECT文を続けると、別のテーブルのデータや、CASE式・JOINの結果を追加できる
- 値を省略したカラムには、デフォルト値・NULL・自動採番の値が入る(NOT NULLのカラムは省略できない)
- 主キーが重複するとエラーになる。上書きしたい場合はON DUPLICATE KEY UPDATEを使う
本記事で紹介した知識を活用して、日々のデータベース作業を効率良く進めていきましょう。
以下では、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エンジニアのスタートラインとして最適です。
話を聞きたい・詳しく知りたいという方はこちらからお気軽にお問い合わせください。
