識別子のクォート方法 - 識別子クォートと大文字小文字 ("" / `` / [])
列名やテーブル名のクォート記号は RDBMS で異なる。ダブルクォート / バッククォート / 角括弧、および大文字小文字の扱いを比較
概念図
構文
sql
"column" / `column` / [column]サンプル
予約語や空白を含む識別子をクォートする書き方
sql
-- ANSI 標準 (PostgreSQL / SQLite / Oracle / SQL Server)
SELECT "user name" FROM "User";
-- MySQL デフォルト
SELECT `user name` FROM `User`;
-- SQL Server 固有 (T-SQL)
SELECT [user name] FROM [User];
-- MySQL で ANSI_QUOTES を有効にすると " も識別子クォートになる
SET sql_mode = 'ANSI_QUOTES';
SELECT "user name" FROM "User"; -- これで動くなぜクォート記号が分かれたのか
ANSI SQL 標準では識別子のクォートに ダブルクォート " を使い、文字列リテラルには シングルクォート ' を使います。PostgreSQL / SQLite / Oracle / SQL Server はこの標準に従っています。
MySQL は当初からダブルクォートも文字列リテラルとして許容していたため、識別子クォート用に バッククォート ` を採用しました。SQL Server は追加で T-SQL 固有の 角括弧 [ ] もサポートします。
RDBMS 別比較表
| RDBMS | 識別子クォート | 文字列リテラル | 大文字小文字 |
|---|---|---|---|
| PostgreSQL | "col" | 'text' | クォート無し: 小文字に畳む / 有り: 区別 |
| MySQL | `col` (ANSI_QUOTES で " も可) | 'text' or "text" (既定) | OS 依存 (Linux: 区別 / Win: 無区別) |
| SQLite | "col" / `col` / [col] | 'text' | 無区別 (ASCII) |
| SQL Server | [col] / "col" (QUOTED_IDENTIFIER 有効時) | 'text' | 照合順序 (collation) で決まる、既定は無区別 |
| Oracle | "col" | 'text' | クォート無し: 大文字に畳む / 有り: 区別 |
大文字小文字の畳み込みに注意
PostgreSQL は クォート無しの識別子を小文字に畳みます。CREATE TABLE "User" のように大文字で作ると、以降は SELECT * FROM "User" のように常にクォート付きで書かなければアクセスできません。
Oracle は逆に大文字に畳みます。Rails や Hibernate の自動生成 SQL が大文字テーブルを作ってしまい、手書きクエリと衝突する事故が多発するのはこのためです。
PostgreSQL / Oracle 系では、テーブル・列名は原則クォートしない(=小/大文字のみ)で統一するのが安全です。
sql
-- PostgreSQL
CREATE TABLE "User" (id INT); -- 「User」という名で作られる
SELECT * FROM User; -- エラー (user に畳まれる)
SELECT * FROM "User"; -- OK
CREATE TABLE users (id INT); -- 推奨: クォート無しで小文字統一
SELECT * FROM Users; -- OK (users に畳まれる)移植時の落とし穴
- MySQL の
"text"を識別子と誤解: デフォルト設定では文字列として動くが、ANSI_QUOTESモードを有効にすると識別子として解釈されるためクエリが壊れる - SQL Server の
[col]は他で動かない: 他 RDBMS に移すなら"col"に置換すればよいが、予約語対策でブラケットを多用している T-SQL はコード量が増える - MySQL のテーブル名 OS 依存: Windows ローカルで動いていた
FROM Usersが Linux 本番ではFROM usersしか通らない事故がある。lower_case_table_names設定を揃える - 予約語を列名にしない:
order,user,group,typeなどは将来の予約語追加で地雷化する。クォートに頼らず避ける - SQL Server の QUOTED_IDENTIFIER: OFF だと
"abc"が文字列リテラルになる。インデックス付きビューや計算列の定義時には必ず ON が必要
