SQL UPDATE徹底比較:MySQL・PostgreSQL・SQL Serverでどう書く?
目次
UPDATE文は基本操作こそどのRDBMSでもほぼ同じだが、細かい機能や構文のクセは意外と差が出る。ここでは MySQL・PostgreSQL・SQL Server を並べて、共通点と違いをわかりやすく整理していく。
基本のUPDATE構文は3製品で共通
まず押さえておきたいのは、ベーシックなUPDATE文はほぼ同じ形で動くこと。
UPDATE users
SET name = 'taro'
WHERE id = 1;
このレベルの基本操作は互換性が高く、移植性も悪くない。
JOINを使ったUPDATEの違い
UPDATEでJOINを使いたい場合、3製品の構文は大きく異なる。
MySQL(JOINをUPDATEに直接書ける)
UPDATE users u
JOIN orders o ON u.id = o.user_id
SET u.status = 'active'
WHERE o.amount > 1000;
PostgreSQL(FROM句でJOIN)
UPDATE users u
SET status = 'active'
FROM orders o
WHERE u.id = o.user_id
AND o.amount > 1000;
SQL Server(FROM句でJOINだがPostgreSQLとは若干書き方が異なる)
UPDATE u
SET u.status = 'active'
FROM users u
JOIN orders o ON u.id = o.user_id
WHERE o.amount > 1000;
JOIN付きUPDATEは3製品で最も差が出る部分なので、移植時はここを重点的にチェックする必要がある。
RETURNING句のサポートの違い
UPDATE後に変更された行を返す機能は製品ごとに差がある。
MySQL
非対応(8.0.16以降「UPDATE … RETURNING」が限定的にサポートされ始めているが、PostgreSQLほど整っていない)
PostgreSQL
全面対応。とても便利。
UPDATE users
SET status = 'active'
WHERE id = 1
RETURNING id, status;
SQL Server
OUTPUT句で同様のことが可能。
UPDATE users
SET status = 'active'
OUTPUT inserted.id, inserted.status
WHERE id = 1;
マルチテーブルUPDATE
MySQLはマルチテーブルUPDATEを独自サポートしている。
MySQL
UPDATE users u, orders o
SET u.status = 'active'
WHERE u.id = o.user_id
AND o.amount > 1000;
PostgreSQLとSQL Serverにはこの構文はなく、JOIN形式で書く必要がある。
TOP / LIMIT の違い(行数制御)
MySQL
UPDATE users
SET status = 'inactive'
WHERE status = 'active'
LIMIT 10;
PostgreSQL
UPDATEに直接LIMITは使えない。サブクエリで対処。
UPDATE users
SET status = 'inactive'
WHERE id IN (
SELECT id FROM users
WHERE status = 'active'
LIMIT 10
);
SQL Server
TOPが使用できる。
UPDATE TOP (10) users
SET status = 'inactive'
WHERE status = 'active';
NULL処理・関数周り
NULL関連の関数に微妙な違いがある。
| 動作 | MySQL | PostgreSQL | SQL Server |
|---|---|---|---|
| NULL時の代替 | IFNULL() | COALESCE() | ISNULL()(SQL Server独自) |
互換性を取るなら COALESCE を使うのが最も安全。
正規表現によるUPDATEの違い
MySQL
UPDATE users
SET status = 'active'
WHERE name REGEXP '^A';
PostgreSQL
UPDATE users
SET status = 'active'
WHERE name ~ '^A';
SQL Server
標準の正規表現は非対応。LIKEで代替する。
全体まとめ
互換性が高い部分
- 基本的なUPDATEの書き方
- WHERE句、SET句
- CASE式(3製品とも対応)
- サブクエリ利用
大きく差が出る部分
- JOIN付きUPDATEの構文
- RETURNING/OUTPUT のサポート
- LIMIT/TOP の挙動
- 正規表現の扱い
- マルチテーブルUPDATE(MySQLのみサポート)
UPDATEは基礎が共通でも、JOINやRETURNING、制御句あたりで一気に差が出るため、複数RDBMSを触るプロジェクトでは特に注意が必要。
基本構文比較
| 項目 | MySQL | PostgreSQL | SQL Server |
|---|---|---|---|
| 基本UPDATE構文 | 共通 | 共通 | 共通 |
| WHERE句 | 共通 | 共通 | 共通 |
| サブクエリ | 共通 | 共通 | 共通 |
| CASE式 | 対応 | 対応 | 対応 |
JOINを使ったUPDATE
| 内容 | MySQL | PostgreSQL | SQL Server |
|---|---|---|---|
| JOIN記述 | UPDATE ... JOIN | UPDATE ... FROM | UPDATE ... FROM |
| JOINの典型例 | UPDATE u JOIN o ... | UPDATE u SET ... FROM o ... | UPDATE u SET ... FROM o ... |
| マルチテーブルUPDATE | 対応(独自構文) | 非対応 | 非対応 |
RETURNING / OUTPUT の対応
| DB | 更新後の値を返す構文 | 例 |
|---|---|---|
| MySQL | 限定的に対応(8.0.16+) | UPDATE ... RETURNING col |
| PostgreSQL | 完全対応 | UPDATE ... RETURNING col |
| SQL Server | OUTPUT句 | UPDATE ... OUTPUT inserted.col |
行数制御(LIMIT / TOP)
| DB | 行数を制限する方法 | 例 |
|---|---|---|
| MySQL | LIMIT | UPDATE ... LIMIT 10 |
| PostgreSQL | 非対応(サブクエリで代替) | WHERE id IN (SELECT ... LIMIT 10) |
| SQL Server | TOP | UPDATE TOP (10) ... |
NULL関連関数
| DB | 代表的なNULL処理 | 備考 |
|---|---|---|
| MySQL | IFNULL() | 独自関数 |
| PostgreSQL | COALESCE() | 標準SQL |
| SQL Server | ISNULL() | 独自関数 |
互換性を重視する場合は COALESCE が共通で使える。
正規表現によるUPDATE
| DB | 正規表現 | 構文 |
|---|---|---|
| MySQL | 対応 | REGEXP |
| PostgreSQL | 対応 | ~ |
| SQL Server | 非対応 | LIKEで代替 |
日付処理の概要
| 操作 | MySQL | PostgreSQL | SQL Server |
|---|---|---|---|
| 現在日時 | NOW() | NOW() | GETDATE() |
| 日付加算 | DATE_ADD() | NOW() + INTERVAL | DATEADD() |
まとめ(特徴比較)
| 特徴 | MySQL | PostgreSQL | SQL Server |
|---|---|---|---|
| JOIN付きUPDATEの書きやすさ | 最も簡潔 | 標準寄り | 標準寄り |
| RETURNINGの強さ | 限定的 | 最も強い | OUTPUTで代替 |
| 行数制御の柔軟性 | 高い | 低い | 高い |
| マルチテーブルUPDATE | 対応 | 非対応 | 非対応 |
| 標準SQL準拠度 | 中 | 高 | 中 |
| ▲ | phpMyAdminでcount(): Parameter must be an array or an object that implements Countable |
| sect: Teches | lastmod: 2018-11-17 | pv: 20 | |