わさっきhb

大学(教育研究)とか ,親馬鹿とか,和歌山とか,とか,とか.

SQLで,列名が予約語のとき

-- 失敗
UPDATE programs SET desc='saezurino mitsuwo' WHERE id=12345;
-- 失敗
UPDATE programs SET 'desc'='saezurino mitsuwo' WHERE id=12345;
-- 成功
UPDATE programs SET "desc"='saezurino mitsuwo' WHERE id=12345;

あるアホな先任者が,「desc」という名前の属性を含むテーブルを作りました.descriptionの先頭を取ったのですが,よく知られているように,「DESC」は,ORDER BY句に添えて,降順にするためのキーワードです.
「あるアホな先任者」の名前を明示するのは差し控えたいと思います.ただ,未来の自分は他人,というところから,お察しください.
さて,プログラムはRubyで書いていて,データベースへのアクセスはActiveRecordを介しているので,問題がなかったのですが,事情で,コマンドラインからデータベースに接続して,特定のレコードの,属性descの値を変更しようとして,苦労したのが,上の3つのSQL文です.
値はもちろん架空のものです.それでも解説しておくと,「saezurino mitsuwo」は「さえずりのみつを」で,DQ4の第2章に「さえずりのみつを てにいれた」と出まして,なんか「あいだみつを」に似てるなあと思ったので,ここに使った次第です.
PostgreSQLのわりかし新しいマニュアルを調査…書いていました.

慣習的には、キーワードを大文字で、名前を小文字で書きます。 例えば下記のようになります。

UPDATE my_table SET a = 5;

識別子には副次的な種類もあります。 区切り識別子あるいは引用符付き識別子です。任意の文字の連なりを二重引用符(")で囲んだものです。区切り識別子は常に識別子であって、キーワードではありません。ですから、"select"は"select"という名前の列あるいはテーブルを問い合わせるために使えますが、引用符の付かないselectはキーワードとして理解されるので、テーブルもしくは列名が期待される部分では解析エラーを起こします。引用符付き識別子は下記の例のように書くことができます。

UPDATE "my_table" SET "a" = 5;

引用符付き識別子は、文字コード0以外であればどのような文字でも使えます(二重引用符を含めたい場合は、二重引用符を2つ入力します)。この決まりがあることによって、普段使えない空白やアンパサンド(&)を含むテーブル名や列名を作ることが可能です。この場合においても長さの制限は適用されます。

引用符が付かない名前は常に小文字に解釈されますが、識別子を引用符で囲むことによって大文字と小文字が区別されるようになります。例えば、識別子FOO、foo、"foo"はPostgreSQLによれば同じものとして解釈されますが、"Foo"と"FOO"は、これら3つとも、またお互いに違ったものとして解釈されます(PostgreSQLが引用符の付かない名前を小文字として解釈することは標準SQLと互換性がありません。標準SQLでは引用符の付かない名前は大文字に解釈されるべきだとされています。したがって標準SQLによれば、fooは"FOO"と同じであるべきで、"foo"とは異なるはずなのです。もし移植可能なアプリケーションを書きたいならば、特定の名前は常に引用符で囲むか、あるいはまったく囲まないかのいずれかに統一することをお勧めします)。

4.1.1. 識別子とキーワード

最新のバージョン8.40の同じページ*1は,上記引用の最後の段落の直前に数段落の説明が入っていて,「U&"foo"」だとか「U&"d\0061t\+000061"」だとか,「U&"\0441\043B\043E\043D"」だとかいった形で識別子が記述可能という,いわゆるUnicode記法について書かれています.