Oracleで「user」という名前のテーブルが作成できなかった
最近、既存システムを刷新することになり、その調査で知ったこと。
Oracleを使用することが決まっていて、プロジェクトの要件、使用するフレームワークなどを確認する過程で、試しにuser
という名前のテーブルを作成しようとしたところ、
SQL> create table user (id number not null, name varchar2(255) not null);
create table user (id number not null, name varchar2(255) not null)
*
行1でエラーが発生しました。 :
ORA-00903: 表名が無効です。
作成できなかった。試したOracleは12c(12.1.0.2.0)。
他に、カラム名をuser
にすると、そのテーブルは作成できない。
SQL> create table foo (id number not null, user varchar2(128) not null);
create table foo (id number not null, user varchar2(128) not null)
*
行1でエラーが発生しました。:
ORA-00904: : 無効な識別子です。
調べたところ、user
はSQLの予約語であり、テーブル名などの識別子として使えない。また、この制約は12cに限ったことではない。
Oracleでは、予約語をV$RESERVED_WORDS
で確認できる。
SQL> set linesize 150
SQL> col RESERVED format a8
SQL> col RES_TYPE format a8
SQL> col RES_ATTR format a8
SQL> col RES_SEMI format a8
SQL> col DUPLICATE format a8
SQL> select * from V$RESERVED_WORDS where keyword = 'USER';
KEYWORD LENGTH RESERVED RES_TYPE RES_ATTR RES_SEMI DUPLICAT CON_ID
------------------------------ ---------- -------- -------- -------- -------- -------- ----------
USER 4 N N N Y N 0
リファレンスによると、Y
になっているRES_SEMI
は、DMLなどのSQLで識別子として利用できない、とのこと。
どうしても予約語を使ったテーブルを作成したい場合は、識別子としてみなされないようにするために引用符をつける。
SQL> create table "user" (id number not null, name varchar2(128) not null);
表が作成されました。
SQL> desc "user";
名前 NULL? 型
----------------------------------------- -------- ----------------------------
ID NOT NULL NUMBER
NAME NOT NULL VARCHAR2(128)
SQL> create table foo (id number not null, "user" varchar2(128) not null);
表が作成されました。
SQL> desc foo;
名前 NULL? 型
----------------------------------------- -------- ----------------------------
ID NOT NULL NUMBER
user NOT NULL VARCHAR2(128)
確かに作成できるが、SQLで指定するときは必ず引用符が必要になる。また、ドキュメントでは、引用符を用いた方法は推奨されていないので、識別子とみなされるワードを使用するのは避けたほうがいい。