Redshift で timestamp というカラム名を SELECT したらシンタックスエラーになる

Redshift で timestamp というカラム名を持つテーブルを SELECT しようとしてハマったので簡単にまとめておく.事象を簡潔に書くと,SELECT で timestamp の後に他のカラムを指定するとシンタックスエラーになるというもの.

結論から言えば,Redshift でも PostgreSQL でも timestamp予約語ではないんだけど,データ型名ではあるので,SELECT するときは必ず引用符で囲ってあげる必要があって,考慮が面倒なのでカラム名にしない方が良いよねっていう話.ただし,動作確認をしてみたところ,Redshift では再現して,PostgreSQL では再現しなかったので,もしかしたら Redshift だけの制約なのかもしれないけど,代替のカラム名が用意できるならその方が良いと思う.

マニュアル (PostgreSQL: Documentation: 9.3: Lexical Structure) にも似たようなことが書かれている.

A delimited identifier is always an identifier, never a key word. So "select" could be used to refer to a column or table named "select", whereas an unquoted select would be taken as a key word and would therefore provoke a parse error when used where a table or column name is expected.

せっかくなので,動作確認をしたログを残しておく.

Redshift で動作確認

idtimestamp というカラムを持つ sample_table テーブルを定義して,サンプルデータを1件挿入する.

xxx=> create table sample_table (id integer, timestamp timestamp);
CREATE TABLE
xxx=> insert into sample_table values (1, '2014-01-01 00:00:00');
INSERT 0 1

id, timestamp の順番だと SELECT は正常に機能する.

xxx=> select id, timestamp from sample_table;
 id |      timestamp      
----+---------------------
  1 | 2014-01-01 00:00:00
(1 row)

逆に timestamp, id の順番にするとシンタックスエラーが出る.

xxx=> select timestamp, id from sample_table;
ERROR:  syntax error at or near ","
LINE 1: select timestamp, id from sample_table;
                        ^

これを解決するためには,ダブルクォーテーションで囲ったり,as で別名を定義したりすれば機能するようになる.

xxx=> select "timestamp", id from sample_table;
      timestamp      | id 
---------------------+----
 2014-01-01 00:00:00 |  1
(1 row)
xxx=> select timestamp as timestamp, id from sample_table;
      timestamp      | id 
---------------------+----
 2014-01-01 00:00:00 |  1
(1 row)

PostgreSQL で動作確認

idtimestamp というカラムを持つ sample_table テーブルを定義して,サンプルデータを1件挿入する.

postgres=# create table sample_table (id integer, timestamp timestamp);
CREATE TABLE
postgres=# insert into sample_table values (1, '2014-01-01 00:00:00');
INSERT 0 1

id, timestamp の順番だと SELECT は正常に機能する.

postgres=# select id, timestamp from sample_table;
 id |      timestamp      
----+---------------------
  1 | 2014-01-01 00:00:00
(1 row)

PostgreSQL の場合は,timestamp, id の順番でも正常に機能する.

postgres=# select timestamp, id from sample_table;
      timestamp      | id 
---------------------+----
 2014-01-01 00:00:00 |  1
(1 row)

当然ながら,ダブルクォーテーションで囲ったり,as で別名を定義しても正常に機能する.

postgres=# select "timestamp", id from sample_table;
      timestamp      | id 
---------------------+----
 2014-01-01 00:00:00 |  1
(1 row)
postgres=# select timestamp as timestamp, id from sample_table;
      timestamp      | id 
---------------------+----
 2014-01-01 00:00:00 |  1
(1 row)