早見表
RDBMS 方言早見表
5 大 RDBMS の記法差を「やりたいこと × エンジン」で横断比較。移植の必携表。
この早見表の使い方
行が「やりたいこと」、列が PostgreSQL / MySQL / SQLite / SQL Server / Oracle の 5 RDBMS です。同じ目的でも記法が異なる箇所をひと目で比べられるようにしてあります。移植前のチェックや、複数 RDBMS を行き来するときの記法確認用に参照してください。個別の詳細は各コマンドページへのリンクを辿ってください。Oracle は 12c 以降を前提に記載しています(バージョン依存のものはその旨を補記)。
基本構文・クエリ
| やりたいこと | PostgreSQL | MySQL | SQLite | SQL Server | Oracle |
|---|---|---|---|---|---|
| 先頭 N 件を取得(詳細) | LIMIT n | LIMIT n | LIMIT n | TOP n または OFFSET 0 ROWS FETCH NEXT n ROWS ONLY | FETCH FIRST n ROWS ONLY(12c+) / 旧式は WHERE ROWNUM <= n |
| ページング(N 件スキップ) | LIMIT n OFFSET m | LIMIT m, n / LIMIT n OFFSET m | LIMIT n OFFSET m | OFFSET m ROWS FETCH NEXT n ROWS ONLY | OFFSET m ROWS FETCH NEXT n ROWS ONLY(12c+) |
| 文字列連結(詳細) | || または CONCAT() | CONCAT()(|| は論理 OR) | || または CONCAT() | + または CONCAT() | || または CONCAT()(2 引数のみ) |
| 識別子クォート(詳細) | "name"(大小区別) | `name` またはバッククォート | "name" / `name` / [name] | [name] または "name" | "name"(既定は大文字、引用時は大小区別) |
| 文字列リテラル | 'abc'(二重化でエスケープ) | 'abc' または "abc" | 'abc' | 'abc'(N'abc' は Unicode) | 'abc'(q'[abc]' リテラルも可) |
| NULL 安全な等値比較 | IS NOT DISTINCT FROM | <=> | IS(限定的) | なし。COALESCE で工夫 | なし。DECODE(a,b,0,1)=0 や NVL で工夫 |
スキーマ定義 (DDL)
| やりたいこと | PostgreSQL | MySQL | SQLite | SQL Server | Oracle |
|---|---|---|---|---|---|
| 自動採番の主キー(詳細) | id SERIAL / GENERATED ALWAYS AS IDENTITY | id INT AUTO_INCREMENT | id INTEGER PRIMARY KEY(ROWID) | id INT IDENTITY(1,1) | GENERATED ALWAYS AS IDENTITY(12c+) / 旧式は SEQUENCE + TRIGGER |
| 直近の採番値を取得 | RETURNING id | LAST_INSERT_ID() | last_insert_rowid() | SCOPE_IDENTITY() / OUTPUT inserted.id | RETURNING id INTO :var / seq.CURRVAL |
| UUID 型 | uuid(ネイティブ) | CHAR(36) / BINARY(16) | TEXT / BLOB | uniqueidentifier | RAW(16) + SYS_GUID() / CHAR(36) |
| 真偽値型 | boolean | TINYINT(1)(BOOLEAN は別名) | INTEGER で 0/1 | BIT | SQL にはなし。NUMBER(1) + CHECK で代用(PL/SQL は BOOLEAN あり) |
| JSON 型 | jsonb(推奨) / json | JSON | TEXT + JSON 関数 | NVARCHAR(MAX) + JSON 関数 | JSON(21c+) / CLOB + IS JSON 制約(12c+) |
| 列コメント | COMMENT ON COLUMN ... | COMMENT '...'(列定義内) | なし(スキーマ外に記録) | sp_addextendedproperty | COMMENT ON COLUMN ... |
| 列追加 | ALTER TABLE t ADD COLUMN c ... | ALTER TABLE t ADD c ... | ALTER TABLE t ADD COLUMN c ...(制限あり) | ALTER TABLE t ADD c ... | ALTER TABLE t ADD (c ...) |
| 列の型変更 | ALTER COLUMN c TYPE ... | MODIFY c ... | 基本不可(再作成) | ALTER COLUMN c ... | MODIFY (c ...) |
データ更新(INSERT / UPSERT)
| やりたいこと | PostgreSQL | MySQL | SQLite | SQL Server | Oracle |
|---|---|---|---|---|---|
| UPSERT(詳細) | INSERT ... ON CONFLICT (k) DO UPDATE SET ... | INSERT ... ON DUPLICATE KEY UPDATE ... | INSERT ... ON CONFLICT (k) DO UPDATE SET ... | MERGE ... WHEN MATCHED ... | MERGE ... WHEN MATCHED ... |
| 更新した行を返す | UPDATE ... RETURNING * | なし(トリガで代用) | UPDATE ... RETURNING * | UPDATE ... OUTPUT inserted.* | UPDATE ... RETURNING ... INTO :var(単一行) |
| JOIN を使った UPDATE | UPDATE t SET ... FROM other WHERE ... | UPDATE t JOIN other SET ... | UPDATE t SET col = (SELECT ... FROM other) | UPDATE t SET ... FROM t JOIN other ... | UPDATE (SELECT t.*, o.v FROM t JOIN other o ON ...) SET ... または MERGE |
| 大量 INSERT の高速化 | COPY コマンド | LOAD DATA INFILE | トランザクション内で多行 INSERT | BULK INSERT / bcp | SQL*Loader / 外部表 / INSERT /*+ APPEND */ |
日付・時刻
| やりたいこと | PostgreSQL | MySQL | SQLite | SQL Server | Oracle |
|---|---|---|---|---|---|
| 現在日時(詳細) | NOW() / CURRENT_TIMESTAMP | NOW() / CURRENT_TIMESTAMP | datetime('now') / CURRENT_TIMESTAMP | GETDATE() / SYSDATETIME() | SYSDATE / SYSTIMESTAMP / CURRENT_TIMESTAMP |
| 現在の日付のみ | CURRENT_DATE | CURDATE() | date('now') | CAST(GETDATE() AS date) | TRUNC(SYSDATE) / CURRENT_DATE |
| 日付を加算 | d + INTERVAL '7 day' | DATE_ADD(d, INTERVAL 7 DAY) | date(d, '+7 day') | DATEADD(day, 7, d) | d + 7(日単位) / ADD_MONTHS(d, 1) / d + INTERVAL '7' DAY |
| 日付の差分(日数) | d1 - d2(days 単位) | DATEDIFF(d1, d2) | julianday(d1) - julianday(d2) | DATEDIFF(day, d2, d1) | d1 - d2(日数) / MONTHS_BETWEEN |
| 書式付きで文字列化 | TO_CHAR(d, 'YYYY-MM-DD') | DATE_FORMAT(d, '%Y-%m-%d') | strftime('%Y-%m-%d', d) | FORMAT(d, 'yyyy-MM-dd') | TO_CHAR(d, 'YYYY-MM-DD') |
| タイムゾーン付き型 | timestamptz | なし(UTC 保存が定石) | なし(TEXT で管理) | datetimeoffset | TIMESTAMP WITH TIME ZONE / TIMESTAMP WITH LOCAL TIME ZONE |
トランザクション・ロック
| やりたいこと | PostgreSQL | MySQL (InnoDB) | SQLite | SQL Server | Oracle |
|---|---|---|---|---|---|
| 既定の分離レベル | READ COMMITTED | REPEATABLE READ | Deferred(WAL モードではスナップショット) | READ COMMITTED(Azure SQL Database は RCSI が既定) | READ COMMITTED |
| 分離レベル変更 | SET TRANSACTION ISOLATION LEVEL ... | SET TRANSACTION ISOLATION LEVEL ... | なし(モードで制御) | SET TRANSACTION ISOLATION LEVEL ... | SET TRANSACTION ISOLATION LEVEL ...(READ COMMITTED / SERIALIZABLE / READ ONLY) |
| 行ロック | SELECT ... FOR UPDATE | SELECT ... FOR UPDATE | なし(DB 全体ロック) | WITH (UPDLOCK, ROWLOCK) | SELECT ... FOR UPDATE |
| ロック取得のスキップ | FOR UPDATE SKIP LOCKED | FOR UPDATE SKIP LOCKED(8.0+) | なし | WITH (READPAST) | FOR UPDATE SKIP LOCKED(18c+ で正式サポート) |
インデックス・実行計画
| やりたいこと | PostgreSQL | MySQL | SQLite | SQL Server | Oracle |
|---|---|---|---|---|---|
| 実行計画を見る | EXPLAIN / EXPLAIN ANALYZE | EXPLAIN / EXPLAIN ANALYZE(8.0+) | EXPLAIN QUERY PLAN | 推定プラン: SET SHOWPLAN_XML ON(後続クエリは実行せず)/実測: SET STATISTICS PROFILE ON または SSMS「実際の実行プランを含める」 | EXPLAIN PLAN FOR ... + SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY) |
| 部分インデックス | CREATE INDEX ... WHERE ... | なし(生成列で代用) | CREATE INDEX ... WHERE ... | フィルタ付きインデックス WHERE ... | なし(関数索引で CASE WHEN ... THEN col END 代用) |
| カバリングインデックス | INCLUDE (cols)(11+) | カバリング扱い(明示構文なし) | カバリング扱い | INCLUDE (cols) | カバリング扱い(明示構文なし) |
| インデックスヒント | なし(プランナ任せ) | USE/FORCE/IGNORE INDEX | なし | WITH (INDEX(name)) | /*+ INDEX(t idx_name) */ |
移植時の注意
- NULL と空文字の扱い: Oracle は空文字
''を NULL とみなすが、他 4 エンジンは「空文字」と「NULL」を別物として扱う。Oracle とそれ以外を行き来する移植でWHERE col = ''の結果が変わる要注意ポイント - 大文字小文字: PostgreSQL は引用符なしの識別子を 小文字化、Oracle は 大文字化、SQL Server は照合順に依存、MySQL は OS により挙動が変わる
- LIMIT 句の位置: SQL 標準の
FETCH FIRST ... ROWS ONLYはORDER BYの後に置く必要がある(PostgreSQL / SQL Server / Oracle 12c+ で利用可) - TRUNCATE の挙動: PostgreSQL / SQL Server はトランザクション内でロールバック可、MySQL / Oracle は DDL 扱いで暗黙コミット(取り消し不可)
- Auto-Increment と ROLLBACK: 多くの RDBMS で採番値はロールバックしても戻らない(ギャップが発生)。Oracle の
SEQUENCEは特に顕著 - DUAL テーブル: Oracle は
FROM句必須のためSELECT 1 FROM DUALのようにダミー表を使う。他エンジンはSELECT 1だけで OK
関連トピック
件数制限の方言 (LIMIT / TOP / FETCH)- SELECT の返却行数を制限する書き方は RDBMS ごとに異なる。LIMIT / TOP / FETCH FIRST の違いと移植のコツを解説 UPSERT の方言 (ON CONFLICT / ON DUPLICATE / MERGE)- 存在すれば UPDATE、無ければ INSERT の UPSERT は RDBMS で記法が大きく異なる。PostgreSQL/MySQL/SQLite/SQL Server の比較 自動採番の方言 (SERIAL / AUTO_INCREMENT / IDENTITY)- 主キーの自動採番は SERIAL / IDENTITY / AUTO_INCREMENT / ROWID と RDBMS ごとに別物。定義方法と挿入直後の ID 取得方法を比較 日付関数の方言 (NOW / DATE_ADD / TO_CHAR)- 現在時刻・日付加算・フォーマットは RDBMS 差分が大きい。NOW / GETDATE / CURRENT_TIMESTAMP、INTERVAL / DATE_ADD / DATEADD を比較 文字列連結の方言 (|| / CONCAT / +)- 文字列連結の演算子は RDBMS で異なる。標準の || / MySQL の CONCAT / SQL Server の + と NULL の扱い 識別子クォートと大文字小文字 ("" / `` / [])- 列名やテーブル名のクォート記号は RDBMS で異なる。ダブルクォート / バッククォート / 角括弧、および大文字小文字の扱いを比較 