SQLのINSERT文は、データベースのテーブルに新しいデータ(行)を追加するために用いられます。追加先のテーブルと、どのカラムにどの値を入れるかを指定して使います。たとえば、会員登録で入力された情報を保存したいときや、注文が入るたびにその記録を残したいときに使います。
INSERT文とは
INSERTは英語で「挿入する」という意味です。追加する値をSQL文の中に直接書くほか、別のテーブルから取り出したデータをまとめて追加することもできます。
INSERT文は、SELECT(取得)・UPDATE(更新)・DELETE(削除)と並ぶ、テーブルの中身を操作するための基本的なSQL文の1つです。
【基本構文】
INSERT文の基本的な構文は、データを挿入するテーブルを指定し、続けて各カラム名とそれに対応するデータの値を指定します。
INSERT INTO テーブル名 (カラム1, カラム2, ...)
VALUES (値1, 値2, ...);INSERT文で指定するのは「どのテーブルに」「どのカラムに」「どんな値を」の3つです。テーブル名のあとの括弧にカラム名をカンマで区切って並べ、VALUESのあとの括弧に、各カラムに登録する値を同じ順番で並べます。1番目のカラムには1番目の値、2番目のカラムには2番目の値が入るため、カラムと値は数・順番・型をそろえる必要があります。
【例】
INSERT INTO test (id,name,gender,point)
VALUES (1005,'鈴木','女',60);テスト(test)テーブルのid・name・gender・pointの4つのカラムに、「1005」「鈴木」「女」「60」を入れる例です。実行すると、鈴木さんのデータが1行追加されます。文字列の値は「’鈴木’」のようにシングルクォート(’)で囲み、数値はそのまま書きます。
この基本の書き方は、MySQL・PostgreSQL・SQL Server・Oracle Databaseなど主要なデータベースで共通です。構文の詳細は各公式リファレンス(MySQL/SQL Server/PostgreSQL)で確認できます。データベースごとに異なる書き方は、「データベースごとの書き方の違い」にまとめています。
INSERT文の基本的な使い方
INSERT文の具体的な使い方を解説していくにあたって、サンプルとして「テスト(test)」テーブルを用意しました。
「テスト(test)」テーブル
| ID(id) | 氏名(name) | 性別(gender) | 点数(point) |
| 1001 | 秋山 | 男 | 80 |
| 1002 | 久保田 | 女 | 100 |
| 1003 | 佐々木 | 女 | 65 |
| 1004 | 佐藤 | 男 | 75 |
手元のMySQLで試す場合は、次のクエリでテーブルを作成し、最初の4件を登録してください(INSERT文の書き方は、このあと順番に解説します)。
【テーブル作成用クエリ】
CREATE TABLE test(
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
gender VARCHAR(10) DEFAULT '-',
point INT NOT NULL
);
INSERT INTO test (id,name,gender,point)
VALUES (1001,'秋山','男',80),(1002,'久保田','女',100),
(1003,'佐々木','女',65),(1004,'佐藤','男',75);ID(id)は主キー(PRIMARY KEY)で、氏名(name)と点数(point)には必ず値が必要なNOT NULLを指定しています。性別(gender)のDEFAULTと、ID(id)のAUTO_INCREMENTは、この章の後半で解説します。
1件のデータを追加する
冒頭の例と同じく、テスト(test)テーブルに鈴木さんのレコードを追加します。
【実行クエリ】
INSERT INTO test (id,name,gender,point)
VALUES (1005,'鈴木','女',60);mysqlコマンドラインツールで実行した場合は、画面に「Query OK, 1 row affected」のように、INSERT文で追加された行数が表示されます。思ったとおりの件数が追加されたかを確認する目安になります。
追加したデータそのものを見たいときは、SELECT文でテーブルの中身を表示します。
【確認用クエリ】
SELECT * FROM test;【実行結果】
| ID(id) | 氏名(name) | 性別(gender) | 点数(point) |
| 1001 | 秋山 | 男 | 80 |
| 1002 | 久保田 | 女 | 100 |
| 1003 | 佐々木 | 女 | 65 |
| 1004 | 佐藤 | 男 | 75 |
| 1005 | 鈴木 | 女 | 60 |
鈴木さんのレコードが追加されました。以降の【実行結果】も、このようにSELECT文でテーブルの中身を表示した結果です。SELECT文の使い方は、以下の記事で解説しています。
複数のデータを一度に追加する
一つの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を行う場合はカラム名を明示することが推奨されています。
なお、このクエリは「1件のデータを追加する」と同じデータを、書き方を変えて示したものです。鈴木さんを追加したあとに続けて実行すると、ID(1005)が重複してエラーになります(「主キーの値が重複している」で解説します)。
一部のカラムだけ指定して追加する
カラム名を書く方法なら、一部のカラムだけを指定して追加できます。指定しなかったカラムには、テーブルを作るときに決めておいた初期値(DEFAULT値)が入ります。
テスト(test)テーブルでは、テーブル作成用クエリの「gender VARCHAR(10) DEFAULT ‘-‘」の部分で、性別(gender)のDEFAULT値を「-」にしています。性別を指定せずに、野村さんを追加してみましょう。
【実行クエリ】
INSERT INTO test (id,name,point)
VALUES (1008,'野村',70);【実行結果】
| ID(id) | 氏名(name) | 性別(gender) | 点数(point) |
| 1001 | 秋山 | 男 | 80 |
| 1002 | 久保田 | 女 | 100 |
| 1003 | 佐々木 | 女 | 65 |
| 1004 | 佐藤 | 男 | 75 |
| 1005 | 鈴木 | 女 | 60 |
| 1006 | 田中 | 男 | 90 |
| 1007 | 土屋 | 女 | 55 |
| 1008 | 野村 | – | 70 |
性別を指定していないため、DEFAULT値の「-」が自動で入りました。
INSERT文で省略したカラムに入る値は、カラムの定義によって次のように変わります(詳しくはMySQL公式リファレンスのデータ型デフォルト値のページを参照)。
| カラムの定義 | 省略したときに入る値 |
| DEFAULT値を設定している | 設定したデフォルト値 |
| DEFAULT値がなく、NULLを許可している | NULL |
| DEFAULT値がなく、NOT NULLを指定している | 省略できない(エラー) |
今回のテーブルでは、氏名(name)と点数(point)にNOT NULLを指定しているため、この2つは省略できません(エラーの例は「NOT NULLのカラムに値を入れていない」で紹介します)。反対に、NULLを許可しているカラムであれば値を省略しておき、あとからUPDATE文で値を入れることもできます。UPDATE文の使い方は、以下の記事で解説しています。
IDを自動で連番にして追加する
テスト(test)テーブルでは、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();」で確認できます(今回は1009が返ります)。追加したレコードのIDを、続けて別のテーブルに登録したいときなどに使います。
INSERT文でよくあるエラーと対処法
INSERT文を書き始めたばかりのころによく出るエラーと、その直し方を紹介します。エラーメッセージはMySQLのもので、エラー番号ごとの意味はMySQL公式のサーバーエラーメッセージリファレンス(英語)で調べられます。
カラムと値の数が合っていない
INSERT INTOで指定したカラムの数と、VALUESに書いた値の数がずれているとエラーになります。次の例では、カラムを4つ指定しているのに値を3つしか書いていません。
【間違った例】
INSERT INTO test (id,name,gender,point)
VALUES (1010,'山口','女');
-- ERROR 1136 (21S01): Column count doesn't match value count at row 1「カラムの数と値の数が一致しない」という意味のエラーです。このエラーが出たら、カラム名と値を1つずつ見比べて、抜けている値や余分な値がないかを確認しましょう。カラム名を省略した場合は、テーブルのカラム数と値の数を比べます。
文字列を引用符で囲んでいない
文字列の値をシングルクォートで囲み忘れると、MySQLはその文字をカラム名として読み取ろうとするため、エラーになります。
【間違った例】
INSERT INTO test (id,name,gender,point)
VALUES (1010,山口,'女',60);
-- ERROR 1054 (42S22): Unknown column '山口' in 'field list'「山口というカラムが見つからない」という意味のエラーです。「’山口’」のようにシングルクォートで囲めば解決します。
日付も「’2026-10-01’」のようにシングルクォートで囲み、数値は「60」のようにそのまま書きます。文字列の中にシングルクォートを含めたい場合は、「’I”m’」のように2つ続けて書きます。詳しいルールはMySQL公式リファレンスの文字列リテラルのページにまとめられています。
NOT NULLのカラムに値を入れていない
NOT NULLを指定していて、デフォルト値もないカラムは、INSERT文で省略できません。テスト(test)テーブルでは氏名(name)と点数(point)が該当します。点数を省略すると、MySQLの初期設定(strictモードが有効な状態)では次のようにエラーになります。
【間違った例】
INSERT INTO test (id,name)
VALUES (1010,'山口');
-- 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の採番をAUTO_INCREMENTに任せましょう。主キーについては、以下の記事で詳しく解説しています。
重複したときに更新・無視したい場合
「同じ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はすでにあるため新しい行は追加されず、秋山さんの点数が80点から85点に更新されました。「AS new」は追加しようとした行に付けた名前で、「new.point」はその行の点数(85)を指します。IDが存在しなかった場合は、通常のINSERTと同じように新しい行が追加されます。この書き方はMySQL 8.0.19以降で使えます(MySQL公式リファレンスのON DUPLICATE KEY UPDATEのページ)。古い記事でよく見る「point = VALUES(point)」という書き方は、MySQL 8.0.20以降は非推奨です。
重複した行を更新せずに無視したいだけなら「INSERT IGNORE INTO ~」と書きますが、重複以外のエラーも警告として扱われて見落としやすくなるため、使う場面は限定しましょう。他のデータベースでの書き方は「データベースごとの書き方の違い」で紹介します。
※以降の章では、秋山さんの点数を元の80点のまま説明します。
別のテーブルのデータをまとめて追加する
INSERT文では、VALUESで値を直接書く代わりにSELECT文の検索結果を追加することもできます。別のテーブルから条件に合うデータだけをコピーしたり、値を加工してから追加したりできるので、データの移行や集計結果の保存によく使われます。
検索結果をそのまま追加する
例として、テスト(test)テーブルから、点数(point)が60点未満の生徒のレコードを新しいテーブル「再テスト(retest)」テーブルに追加します。ここまでの操作で、テスト(test)テーブルは次の9件になっています。
「テスト(test)」テーブル
| ID(id) | 氏名(name) | 性別(gender) | 点数(point) |
| 1001 | 秋山 | 男 | 80 |
| 1002 | 久保田 | 女 | 100 |
| 1003 | 佐々木 | 女 | 65 |
| 1004 | 佐藤 | 男 | 75 |
| 1005 | 鈴木 | 女 | 60 |
| 1006 | 田中 | 男 | 90 |
| 1007 | 土屋 | 女 | 55 |
| 1008 | 野村 | – | 70 |
| 1009 | 森 | 男 | 85 |
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句の「point < 60」という条件で、testテーブルから60点未満のレコードだけを取り出して追加しています。WHERE句の基本は、以下の記事で解説しています。
【実行結果】
| ID(id) | 氏名(name) | 性別(gender) | 点数(point) |
| 1007 | 土屋 | 女 | 55 |
60点未満の生徒のデータだけが抽出され、新しいテーブルに登録されました。
この書き方ではVALUESは使わず、INSERT INTOのあとにそのままSELECT文を続けます。INSERT INTOで指定したカラムには、SELECTで取得したカラムが左から順番に入るため、ここでもカラムの数と順番を合わせておきましょう。この書き方はMySQL公式リファレンスのINSERT … SELECTのページでも解説されています。
SELECT文の条件しだいで追加される件数が変わるため、INSERTを実行する前にSELECTの部分だけを実行して、追加される行を確かめておくと安心です。実行後は、mysqlコマンドラインツールに「Records: 1 Duplicates: 0 Warnings: 0」のように追加された件数が表示されます。
条件によって値を変えて追加する
SELECT文の中でCASE式を使うと、条件に応じて値を変えてから追加できます。CASE式は、データごとに条件にあてはまるかを判定し、判定結果に応じて異なる値を返す書き方です。ここでは、テスト(test)テーブルの点数をもとに成績を付けて、「成績(grades)」テーブルに追加します。
【テーブル作成用クエリ】
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 | 不可 |
| 1008 | 野村 | 70 | 良 |
| 1009 | 森 | 85 | 優 |
SELECT文で取得した「id」「name」「point」と、CASE式で判定した成績の4つが、INSERT INTOで指定した4つのカラムに順番どおりに入っています。
CASE式のWHENは上から順番に判定され、最初に条件を満たしたWHENの値が使われます。そのため、100点の久保田さんは「point >= 80」の条件も満たしていますが、先に判定される「point >= 90」に当てはまった時点で「秀」に決まります。どの条件にも当てはまらない場合は、ELSEの「不可」が入ります。
なお、「〇点以上」のような範囲の条件は、上のように「CASE」の直後には何も書かず、WHENのあとに条件を書きます。「CASE point WHEN …」の形(単純CASE式)は値が等しいかどうかしか比べられないため、範囲の判定には使えません。
また、SELECT文で取得した複数のレコードをまとめてINSERTするときは、「VALUES( SELECT … )」のようにVALUESの中にSELECT文を入れるのではなく、INSERT INTOのあとにSELECT文を直接続けます。
CASE式の詳しい使い方は、以下の記事で解説しています。
複数のテーブルを結合した結果を追加する
INSERT INTOに続けるSELECT文にはJOIN句も書けるため、複数のテーブルを結合した結果をまとめて追加できます。ここでは、次の2つのテーブルを使います。
「生徒(student)」テーブル
| 学籍番号(number) | 氏名(name) | 部活ID(club_id) |
| 1 | 菊池 | 1 |
| 2 | 鈴木 | 3 |
| 3 | 田中 | 4 |
| 4 | 山田 | 1 |
「運動部(sport_club)」テーブル
| ID(id) | 競技(sport) |
| 1 | 野球 |
| 2 | サッカー |
| 3 | バスケットボール |
「生徒」テーブルの部活ID(club_id)と「運動部」テーブルのID(id)を結合し、運動部に所属する生徒の氏名と競技を、新しい「運動部所属者(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) |
| 菊池 | 野球 |
| 鈴木 | バスケットボール |
| 山田 | 野球 |
JOIN(内部結合)では、結合条件に一致しない行は結果に含まれません。そのため、部活IDが「運動部」テーブルにない田中さんのレコードは追加されていません。INSERTの前にSELECTの部分だけを実行しておけば、こうした抜けにも事前に気づけます。結合相手がない生徒も含めてすべて追加したい場合は、LEFT JOIN(外部結合)を使います。結合の種類については、以下の記事で詳しく解説しています。
なお、別のテーブルから値を1つだけ取ってきたい場合は、VALUESの中にSELECT文(サブクエリ)を書く方法もあります。たとえば、新しい生徒を「生徒」テーブルに追加するときに、部活IDを番号ではなく競技名から調べて登録できます。
【実行クエリ】
INSERT INTO student (number,name,club_id)
VALUES (5,'高橋',(SELECT id FROM sport_club WHERE sport = 'サッカー'));カッコ内のSELECT文で「サッカー」のIDである2が取得され、高橋さんのclub_idに2が入ります。このようにVALUESの中で使うSELECT文は、1行1列(値1つ)を返すように書く必要があります。条件に当てはまる行が2行以上あると「ERROR 1242 (21000): Subquery returns more than 1 row」というエラーになり、1行も当てはまらない場合はサブクエリの結果がNULLになります。
生徒テーブルの部活IDのように、別のテーブルのIDを参照するカラムと外部キーの関係は、以下の記事で解説しています。
大量のデータを追加するときのポイント
追加するレコードが数件なら、1件ずつINSERT文を書いても問題ありません。しかし、数千件・数万件といった大量のデータを1件ずつINSERTすると、実行に時間がかかり、データベースにも負荷がかかります。
そこで使うのが、少ない回数のINSERT文で大量のレコードをまとめて追加する「バルクインサート」(Bulk Insert)です。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文ごとに変更を確定する機能)をオフにして、最後のCOMMITでまとめて確定する方法もあります(MySQL公式ドキュメントのInnoDBテーブルの一括データロードのページで紹介されている方法です)。途中で間違いに気づいたら、COMMITの代わりにROLLBACKを実行すれば追加をまとめて取り消せます。
SET autocommit=0;
INSERT INTO test (id,name,gender,point) VALUES (...),(...),(...);
INSERT INTO test (id,name,gender,point) VALUES (...),(...),(...);
COMMIT;
SET autocommit=1;CSVファイルなどから大量のデータを取り込む場合は、MySQLの「LOAD DATA」文のような専用の方法を使うと、通常のINSERT文よりさらに速く取り込めます(公式ドキュメントでは、20倍ほど速いことが多いと説明されています)。
データベースごとの書き方の違い
「INSERT INTO テーブル名 (カラム) VALUES (値)」という基本の書き方は、MySQL・PostgreSQL・SQL Server・Oracle Databaseのどれでも同じです。一方で、複数行の追加や自動採番、重複時の更新などは、データベースによって書き方が異なります。
| やりたいこと | MySQL | PostgreSQL | SQL Server | Oracle Database |
| 複数行をまとめて追加 | VALUESに複数の組を並べる | VALUESに複数の組を並べる | VALUESに複数の組を並べる(1回1,000行まで) | 23ai以降はVALUESに複数の組を並べられる。それ以前はINSERT ALLなどを使う |
| IDの自動採番 | AUTO_INCREMENT | IDENTITY列(GENERATED … AS IDENTITY)、SERIAL | IDENTITY | IDENTITY列、シーケンス |
| 重複したら更新(UPSERT) | ON DUPLICATE KEY UPDATE | ON CONFLICT … DO UPDATE | MERGE | MERGE |
| 追加したIDを取得 | LAST_INSERT_ID() | RETURNING | OUTPUT | RETURNING … INTO |
| 自動採番のカラムに値を直接入れる | そのまま値を指定できる | SERIAL・BY DEFAULTならそのまま指定できる(ALWAYSはOVERRIDING SYSTEM VALUEが必要) | SET IDENTITY_INSERT テーブル名 ON が必要 | BY DEFAULTならそのまま指定できる(ALWAYSは指定できない) |
SQL Serverでは、追加した行の値をOUTPUT句で受け取れます。次の例は、idをIDENTITY(自動採番)にしたテスト(test)テーブルに1件追加し、採番されたidを表示します。
【SQL Serverの例:追加したIDを取得する】
INSERT INTO test (name,gender,point)
OUTPUT INSERTED.id
VALUES (N'山口',N'女',60);OUTPUT句は、カラム名の指定とVALUESのあいだに書きます。また、SQL ServerでNVARCHAR型のカラムに日本語を入れるときは、「N’山口’」のように文字列の前にNを付けます。付けないと、データベースの照合順序によっては文字が「?」に置き換わることがあります。
IDENTITYのカラムに自分で決めた値を入れたい場合は、一時的にIDENTITY_INSERTをONにします。このとき、INSERT文ではカラム名の指定が必須です。
【SQL Serverの例:IDENTITYのカラムに値を指定する】
SET IDENTITY_INSERT test ON;
INSERT INTO test (id,name,gender,point)
VALUES (2001,N'森田',N'男',70);
SET IDENTITY_INSERT test OFF;各データベースの詳しい書き方は、公式ドキュメント(PostgreSQLのINSERT、SQL ServerのINSERT、Oracle DatabaseのINSERT)で確認できます。
INSERT文に関するよくある質問
Q. INSERTしたデータを取り消すには?
A. MySQLは初期設定では、INSERT文を実行した時点で変更が確定します(自動コミット)。確定したデータを消すには、DELETE文で削除します。あとから取り消す可能性がある場合は、「START TRANSACTION;」を実行してからINSERTすると、「ROLLBACK;」で追加前の状態に戻せます(問題なければ「COMMIT;」で確定します)。
START TRANSACTION;
INSERT INTO test (id,name,gender,point) VALUES (1010,'山口','女',60);
ROLLBACK; -- 山口さんの追加が取り消されるDELETE文の使い方は、【SQL】データ削除「DELETE文」の使い方で解説しています。
Q. INSERTとUPDATEの違いは?
A. INSERTは新しい行を追加するとき、UPDATEはすでにある行の値を書き換えるときに使います。たとえば、秋山さんの点数を変えたいときにINSERTを使うと、主キーの重複エラーになるか、別の行として追加されてしまいます。既存のデータを変えるときはUPDATE文を使いましょう(「重複したときに更新・無視したい場合」で紹介したON DUPLICATE KEY UPDATEは、この2つを組み合わせた書き方です)。
Q. INSERT INTOの「INTO」は省略できる?
A. MySQLとSQL Serverでは「INSERT test (…) VALUES (…)」のように省略できますが、PostgreSQLでは省略できません。データベースを問わず動くように、INTOは省略せずに書くのがおすすめです。
Q. 一度に何件まで追加できる?
A. MySQLでは、VALUESに並べる行数そのものに上限はありませんが、1つのSQL文の大きさが設定値(max_allowed_packet、MySQL 8.0以降の初期値は64MB)を超えるとエラーになります。SQL Serverでは、VALUESに並べられるのは1回あたり1,000行までです。大量のデータを追加する場合は、「大量のデータを追加するときのポイント」のように、数百〜数千行ずつ分けて実行しましょう。
まとめ
私たちが日々行うデータの操作の中でも、INSERT文はよく使われるSQL文の1つです。本記事のポイントは次のとおりです。
- INSERT文は「INSERT INTO テーブル名 (カラム) VALUES (値)」の形で書き、カラムと値の数・順番・型をそろえる
- 文字列や日付はシングルクォートで囲む
- VALUESのあとに複数の組を並べると、一度に複数のレコードを追加できる
- 値を省略したカラムには、デフォルト値・NULL・自動採番の値が入る(NOT NULLのカラムは省略できない)
- 主キーが重複するとエラーになる。上書きしたい場合はON DUPLICATE KEY UPDATEを使う
- INSERT INTOのあとにSELECT文を続けると、別のテーブルのデータや、CASE式・JOINの結果をまとめて追加できる
- 複数行の追加や自動採番、重複時の更新は、データベースによって書き方が異なる
本記事で紹介した知識を活用して、日々のデータベース作業を効率良く進めていきましょう。
以下では、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エンジニアのスタートラインとして最適です。
話を聞きたい・詳しく知りたいという方はこちらからお気軽にお問い合わせください。
