最終更新日:2025年11月20日

SQL INSERT徹底比較:MySQL・PostgreSQL・SQL Serverでどう書く?

記事内に商品プロモーションを含む場合があります。

INSERT文はどのRDBMSでも基本的には同じ使い方ができるが、細かい仕様は製品ごとに違いがある。ここでは MySQL・PostgreSQL・SQL Server の3つを並べて、共通点と相違点を整理していく。

基本のINSERT構文は共通

3製品とも、最もシンプルなINSERTは同じ形で書ける。

INSERT INTO users (name, age)
VALUES ('taro', 20);

複数行INSERTも共通で書ける。

INSERT INTO users (name, age)
VALUES ('taro', 20), ('jiro', 22), ('hanako', 19);

実務ではまずここを押さえておけば問題ない。

AUTO_INCREMENT / SERIAL / IDENTITY の扱い

自動採番カラムはDBごとに仕様が異なる。

MySQL

id INT AUTO_INCREMENT

PostgreSQL

id SERIAL
-- または
id INT GENERATED ALWAYS AS IDENTITY

SQL Server

id INT IDENTITY(1,1)

INSERT時にIDカラムは省略すれば自動で採番されるのはどれも同じ。ただし、採番値を明示的に挿入する場合は挙動が違う。

自動採番の値を取得する方法

INSERT直後のIDを取得する方法は特に違いが大きい。

MySQL

SELECT LAST_INSERT_ID();

PostgreSQL

INSERT INTO users (name) VALUES ('taro') RETURNING id;

SQL Server

SELECT SCOPE_IDENTITY();

PostgreSQLのRETURNING句は特に便利で、複数列を返すことも可能。

INSERT … SELECT の違い

別テーブルからデータをコピーする構文は概ね同じだが、SQL Serverの列指定が少し柔軟。

共通構文(MySQL / PostgreSQL / SQL Server)

INSERT INTO new_users (name, age)
SELECT name, age FROM users WHERE age > 20;

どのDBでも問題なく使える。

ON DUPLICATE / ON CONFLICT / MERGE の違い

重複時の挙動は3製品で仕様が大きく異なる部分。

MySQL(ON DUPLICATE KEY UPDATE)

INSERT INTO users (id, name)
VALUES (1, 'taro')
ON DUPLICATE KEY UPDATE name = 'taro';

PostgreSQL(ON CONFLICT)

INSERT INTO users (id, name)
VALUES (1, 'taro')
ON CONFLICT (id) DO UPDATE SET name = 'taro';

SQL Server(MERGE)

MERGE INTO users AS u
USING (VALUES (1, 'taro')) AS s(id, name)
ON u.id = s.id
WHEN MATCHED THEN UPDATE SET name = s.name
WHEN NOT MATCHED THEN INSERT (id, name) VALUES (s.id, s.name);

役割は似ていても書き方が全く違うため、移植時の注意点になる。

DEFAULT値の扱い

DEFAULTを明示的に入れたい場合の記述が少し異なる。

MySQL / PostgreSQL

INSERT INTO users (name, age)
VALUES ('taro', DEFAULT);

SQL Server

INSERT INTO users (name, age)
VALUES ('taro', DEFAULT);

ここは3製品でほぼ共通。

バルクINSERT(大量データ挿入)

MySQL

LOAD DATA INFILE 'data.csv'
INTO TABLE users
FIELDS TERMINATED BY ',';

PostgreSQL

COPY users FROM '/path/data.csv' CSV;

SQL Server

BULK INSERT users
FROM 'C:\data.csv'
WITH (FIELDTERMINATOR = ',', ROWTERMINATOR = '\n');

高速処理が必要な場合、これら専用コマンドを使うと効率が大きく変わる。

まとめ

INSERT文はどのDBでも基本構文こそ同じだが、
特に大きく異なるポイントは次の通り。

複数RDBMSを扱う場面では、互換性を確保したい部分は標準構文で揃え、DBごとに異なる機能は用途に応じて使い分けるのが安全。

項目MySQLPostgreSQLSQL Server
基本INSERT構文共通共通共通
複数行INSERT対応対応対応
自動採番AUTO_INCREMENTSERIAL / IDENTITYIDENTITY
ID取得方法LAST_INSERT_ID()RETURNINGSCOPE_IDENTITY()
重複時の処理ON DUPLICATE KEY UPDATEON CONFLICTMERGE
INSERT … SELECT対応対応対応
DEFAULT の明示DEFAULTDEFAULTDEFAULT
バルクINSERTLOAD DATA INFILECOPYBULK INSERT
トランザクション内の動作安定安定注意点あり(特にMERGE)

重複時の挙動比較

要素MySQLPostgreSQLSQL Server
キー衝突時の簡易更新可能可能単独構文なし
構文ON DUPLICATE KEY UPDATEON CONFLICTMERGE
初心者向きの書きやすさ高い高い低い(構文が長い)

自動採番の仕様比較

項目MySQLPostgreSQLSQL Server
自動採番の宣言方法AUTO_INCREMENTSERIAL / IDENTITYIDENTITY
指定しないINSERT時の挙動自動採番自動採番自動採番
任意値の挿入SET sql_modeによる制御明示的に可能IDENTITY_INSERTが必要

ID取得方法比較

DB方法
MySQLLAST_INSERT_ID()SELECT LAST_INSERT_ID();
PostgreSQLRETURNINGINSERT ... RETURNING id;
SQL ServerSCOPE_IDENTITY()SELECT SCOPE_IDENTITY();

バルク処理比較

DB構文備考
MySQLLOAD DATA INFILE高速で実務で広く使われる
PostgreSQLCOPY圧倒的に高速、定番
SQL ServerBULK INSERTパス指定や権限に注意
SQL INSERT徹底比較:MySQL・PostgreSQL・SQL Serverでどう書く?の商品をアマゾンで調べる。
SQL DELETE徹底比較:MySQL・PostgreSQL・SQL Serverでどう書く?
sect: Sqls | lastmod: 2025-11-20 | pv: 0
SQL SELECT徹底比較:MySQL・PostgreSQL・SQL Serverでどう書く?
sect: Sqls | lastmod: 2025-11-20 | pv: 0
SQL UPDATE徹底比較:MySQL・PostgreSQL・SQL Serverでどう書く?
sect: Sqls | lastmod: 2025-11-20 | pv: 0
SQLServer nolockを使ってテーブルをロックせずにSELECTする
sect: Teches | lastmod: 2019-04-30 | pv: 10121
phpMyAdminでcount(): Parameter must be an array or an object that implements Countable
sect: Teches | lastmod: 2018-11-17 | pv: 20