今日もプログラミング

IT技術とかプログラミングのこととか特にJavaを中心に書いていきます

データベースのテーブル名で大文字と小文字は区別される?

embulk-output-oracleを使っている方から、テーブルがあるのにエラーになってしまう、という問い合わせがあった。

調べてみると、テーブル名は大文字なのに、設定ファイルは小文字で書いてある。

普通にOracleSQLを書くと大文字/小文字は区別されないが、embulk-output-jdbcではテーブル名を引用符で囲んだSQLを構築する。

Oracleでは引用符で囲むと大文字/小文字が区別されてしまうのだ。

うーん、各DBMSで大文字/小文字が区別されるかどうか、まとめておいた方がよさそうだ。

 

Oracle

データベース・オブジェクトのネーミング規則

9. 引用符のない識別子は、大/小文字が区別されません。
引用符のない識別子は大文字として解析されます。
引用識別子では、大文字と小文字が区別されます。

実際にやってみた。

SQL> CREATE TABLE TEST(ID CHAR(2));

表が作成されました。

SQL> SELECT * FROM TEST;

レコードが選択されませんでした。

SQL> SELECT * FROM test;

レコードが選択されませんでした。

SQL> SELECT * FROM "TEST";

レコードが選択されませんでした。

SQL> SELECT * FROM "test";
SELECT * FROM "test"
              *
行1でエラーが発生しました。:
ORA-00942: 表またはビューが存在しません。

MySQL

MySQL :: MySQL 5.6 リファレンスマニュアル :: 9.2.2 識別子の大文字と小文字の区別

データベース内の各テーブルも、...ファイルに対応しています。
...
この結果、基になるオペレーティングシステムで大文字と小文字が区別されるかどうかが、
データベース名、テーブル名、およびトリガー名で大文字と小文字が区別されるかどうかに影響します。
これは、Windows ではこれらの名前は大文字と小文字が区別されませんが、
多くの Unix では大文字と小文字が区別されることを意味します。

なるほど。OSによって違うのか。

 

MySQL :: MySQL 5.6 リファレンスマニュアル :: 9.2 スキーマオブジェクト名

引用符と大文字/小文字の区別については書かれていなかった。

実際Windowsで試してみると、区別されなかった。

mysql> create table xyz (id char(2));
Query OK, 0 rows affected (0.06 sec)

mysql> select * from xyz;
Empty set (0.00 sec)

mysql> select * from XYZ;
Empty set (0.00 sec)

mysql> select * from `xyz`;
Empty set (0.00 sec)

mysql> select * from `XYZ`;
Empty set (0.00 sec)

Linuxだと大文字と小文字は区別される。

mysql> create table xyz (id char(2));
Query OK, 0 rows affected (0.02 sec)

mysql> select * from xyz;
Empty set (0.00 sec)

mysql> select * from XYZ;
ERROR 1146 (42S02): Table 'test.XYZ' doesn't exist
mysql> select * from `xyz`;
Empty set (0.00 sec)

mysql> select * from `XYZ`;
ERROR 1146 (42S02): Table 'test.XYZ' doesn't exist

 

PostgreSQL

4.1.1. 識別子とキーワード

キーワードと引用符付きでない(クォートされていない)識別子は大文字と小文字を区別しません。

なるほど、逆に、引用符を付けると大文字/小文字が区別されるのかな。

postgres=# create table xyz(id char(2));
CREATE TABLE
postgres=# select * from xyz;
 id
----
(0 行)


postgres=# select * from XYZ;
 id
----
(0 行)


postgres=# select * from "xyz";
 id
----
(0 行)


postgres=# select * from "XYZ";
ERROR:  リレーション"XYZ"は存在しません
行 1: select * from "XYZ";
                    ^

確かに区別された。

 

SQL Server

データベース識別子

テーブル名、ビュー名、列名など、データベース内のオブジェクトの識別子には、
データベースの既定の照合順序が指定されます。 
たとえば、大文字と小文字を区別する照合順序が指定されたデータベースでは、
同じ名前で大文字と小文字のみが異なる 2 つのテーブルを作成できますが、
大文字と小文字を区別しない照合順序が指定されたデータベースでは作成できません。 

SQL Serverでは、照合順序の設定により、どちらでも選べるようだ。

例えば、"Japanese_CI_AS"のように"CI"を含む場合は区別しない。"CS"を含む場合は区別する。

引用符(""や[])と大文字/小文字の区別については書かれていない。

"Japanese_CI_AS"で以下を実行したら、正常に実行できた。

CREATE TABLE XYZ(ID CHAR(2));
SELECT * FROM XYZ;
SELECT * FROM xyz;
SELECT * FROM "XYZ";
SELECT * FROM "xyz";
SELECT * FROM [XYZ];
SELECT * FROM [xyz];

 

まとめ

まとめると、こんな感じか。

DBMS大文字と小文字の区別
Oracle 引用符で囲むと区別される
MySQL 大文字と小文字のファイル名を区別するOSでは区別される
PostgreSQL 引用符で囲むと区別される
SQL Server 照合順序の設定によっては区別される

embulk-output-jdbcではテーブル名を引用符で囲むので、OraclePostgreSQLでは要注意だ。 

 

Oracle 12c
MySQL 5.6
PostgreSQL 9.4
SQL Server 2012