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でも基本構文こそ同じだが、
特に大きく異なるポイントは次の通り。
- 自動採番の仕組みとID取得方法
- 重複時の挙動(ON DUPLICATE / ON CONFLICT / MERGE)
- バルク処理の方法
- 日付、関数、シーケンスなどの周辺仕様
複数RDBMSを扱う場面では、互換性を確保したい部分は標準構文で揃え、DBごとに異なる機能は用途に応じて使い分けるのが安全。
| 項目 | MySQL | PostgreSQL | SQL Server |
|---|---|---|---|
| 基本INSERT構文 | 共通 | 共通 | 共通 |
| 複数行INSERT | 対応 | 対応 | 対応 |
| 自動採番 | AUTO_INCREMENT | SERIAL / IDENTITY | IDENTITY |
| ID取得方法 | LAST_INSERT_ID() | RETURNING句 | SCOPE_IDENTITY() |
| 重複時の処理 | ON DUPLICATE KEY UPDATE | ON CONFLICT | MERGE |
| INSERT … SELECT | 対応 | 対応 | 対応 |
| DEFAULT の明示 | DEFAULT | DEFAULT | DEFAULT |
| バルクINSERT | LOAD DATA INFILE | COPY | BULK INSERT |
| トランザクション内の動作 | 安定 | 安定 | 注意点あり(特にMERGE) |
重複時の挙動比較
| 要素 | MySQL | PostgreSQL | SQL Server |
|---|---|---|---|
| キー衝突時の簡易更新 | 可能 | 可能 | 単独構文なし |
| 構文 | ON DUPLICATE KEY UPDATE | ON CONFLICT | MERGE |
| 初心者向きの書きやすさ | 高い | 高い | 低い(構文が長い) |
自動採番の仕様比較
| 項目 | MySQL | PostgreSQL | SQL Server |
|---|---|---|---|
| 自動採番の宣言方法 | AUTO_INCREMENT | SERIAL / IDENTITY | IDENTITY |
| 指定しないINSERT時の挙動 | 自動採番 | 自動採番 | 自動採番 |
| 任意値の挿入 | SET sql_modeによる制御 | 明示的に可能 | IDENTITY_INSERTが必要 |
ID取得方法比較
| DB | 方法 | 例 |
|---|---|---|
| MySQL | LAST_INSERT_ID() | SELECT LAST_INSERT_ID(); |
| PostgreSQL | RETURNING句 | INSERT ... RETURNING id; |
| SQL Server | SCOPE_IDENTITY() | SELECT SCOPE_IDENTITY(); |
バルク処理比較
| DB | 構文 | 備考 |
|---|---|---|
| MySQL | LOAD DATA INFILE | 高速で実務で広く使われる |
| PostgreSQL | COPY | 圧倒的に高速、定番 |
| SQL Server | BULK INSERT | パス指定や権限に注意 |
| ▲ | phpMyAdminでcount(): Parameter must be an array or an object that implements Countable |
| sect: Teches | lastmod: 2018-11-17 | pv: 20 | |