PostgreSQL vs MySQL
PostgreSQLとMySQLの
SQL方言の違いを比較
Web開発でよく使われる2つのRDBMS。似ているようで少し違うSQLの書き方を、実際にブラウザで書き比べてみましょう。
CONCAT()と||、AUTO_INCREMENTとSERIALなど、目的は同じでもPostgreSQLとMySQLでは代表的な書き方が異なります。
SQL Dialects
代表的な書き方を比べてみる
まずは、実務でも違いに気づきやすい代表的な構文だけを並べてみます。
| やりたいこと | PostgreSQL | MySQL |
|---|---|---|
| 文字列結合 | a || b | CONCAT(a, b) |
| IDの自動採番 | SERIAL / IDENTITY | AUTO_INCREMENT |
| NULLの置換 | COALESCE() | IFNULL() |
| 大文字小文字を無視した検索 | ILIKE | 照合順序などに依存 |
| 件数制限 | LIMIT | LIMIT |
文字列結合と「NULL」の落とし穴
標準SQLに準拠するPostgreSQLやOracle Databaseでは、||(パイプ2つ)演算子で文字列を結合します。
SELECT first_name || ' ' || last_name
FROM users;
一方、MySQLでは CONCAT() 関数を使って結合するのが最も一般的です。
SELECT CONCAT(first_name, ' ', last_name)
FROM users;
① MySQLで「||」を使うとどうなる?
MySQLのデフォルト設定では、|| は文字列結合ではなく「論理OR(どちらかが真なら1)」として計算されます。そのため、文字列同士を || で繋ぐと結果が 0 になってしまう事故が多発します。(※MySQL側の設定で PIPES_AS_CONCAT モードを有効にすれば || でも結合可能です)。
② PostgreSQLでCONCAT()を使うときの「NULL」の扱い
実は最近のPostgreSQLでも CONCAT() 関数は使えます。しかし、最大の注意点は「NULLが含まれていた時の挙動」です。|| を使って 'A' || NULL と書くと結果は全体が NULL に消滅してしまいます。しかし、CONCAT('A', NULL) の場合はNULLが無視されて 'A' が返ります。DB移行時にバグを生みやすい非常に重要な違いです。
自動採番も、書き方が違う
PostgreSQLの既存コードでは、自動採番列としてSERIALを目にすることがあります。
CREATE TABLE items (
id SERIAL PRIMARY KEY,
name VARCHAR(100)
);
MySQLではAUTO_INCREMENTが代表的です。
CREATE TABLE items (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100)
);
データ型と文字の囲み方の決定的な違い
構文(方言)以上に、実務でのDB移行や、複数RDBMSを併用するエンジニアを苦しめるのが「データ型」と「文字の囲み方(クォーテーション)」のルールの違いです。
| 比較ポイント | PostgreSQL | MySQL |
|---|---|---|
| 真偽値 (Boolean) | ネイティブな BOOLEAN 型が存在(TRUE / FALSE) |
実は内部的に TINYINT(1) として扱われる(1 / 0) |
| テーブル名の囲み文字 | ダブルクォーテーション "users" |
バッククォート `users`(ANSIモード以外) |
| 大文字・小文字の検索 | 厳密に区別する。無視したい場合は ILIKE を使う |
デフォルトの照合順序設定では区別しない(Aとaは同じ扱い) |
例えば、MySQLでは文字列をダブルクォーテーション(")で囲んでも許容されることが多いですが、PostgreSQLを含む標準SQLの世界では「文字列はシングルクォート(')、カラム名やテーブル名などの識別子はダブルクォート(")」と厳格に定められています。
また、大文字・小文字の検索ルールが根本から違うため、MySQLで動いていた「メールアドレスの重複チェック」システムをPostgreSQLに移行した途端、大文字小文字の違いで重複登録がすり抜けてしまうといったインシデントに繋がることもあります。
実務での「DB移行」で起きるエラー
システム開発の途中で「PostgreSQLからMySQLへ移行する(またはその逆)」というケースは実務でも発生します。その際、単純にデータを移すだけではアプリケーションが動きません。
- 文字列の囲み方: MySQLはダブルクォーテーション
"を文字列として許容しますが、PostgreSQLでは識別子(カラム名など)とみなされてエラーになります(標準SQLではシングルクォーテーション'が正解です)。 - 大文字・小文字の検索: PostgreSQLには大文字小文字を無視する
ILIKEがありますが、MySQLには存在しません(MySQLは照合順序の設定に依存します)。
このように、RDBMSごとの「方言」を知らないまま開発を進めると、後から膨大なSQLの書き換え作業が発生してしまいます。
Compare in Browser
読むより、書き比べるのが一番早い。
表を眺めるだけでも違いはわかりますが、実際にSQLを書くとさらに明確になります。
Miria SQL Learningでは、PostgreSQLモードとMySQLモードを切り替えながら、同じ目的のSQLをそれぞれの書き方で試せます。
Try Comparison
2つのDBを
書き比べよう。
アプリ内でモードを切り替えると、同じ構文でもエラーに
なったり、結果が変わるのを体験できます。
Related Guides
他のガイドを確認する
POSTGRESQL
PostgreSQLモード
SERIAL、RETURNING、ILIKEなど、PostgreSQLでよく使う書き方を確認します。
PostgreSQLガイドへMYSQL
MySQLモード
AUTO_INCREMENT、CONCAT()、IFNULL()など、MySQLらしい書き方を確認します。
MySQLガイドへRDBMS GUIDES
他のRDBMSも見る
Oracle DBやSQLiteを含めたRDBMS別のSQL方言ガイド一覧へ戻ります。
RDBMSガイド一覧へ