HHeLiBeXの日記 正道編

日々の記憶の記録とメモ‥

識別子の大文字と小文字の違い

時々、CREATE TABLE文を書くときには

CREATE TABLE "HOGE"("ID" INTEGER, "NAME" VARCHAR(8))

のように書くのに、INSERT文では

INSERT INTO HOGE(ID, NAME) VALUES(12345678, 'hhelibex')

のように書いている、というケースを見かける。
確かに、SQLでは、テーブル名や列名などの識別子の大文字・小文字は基本的に区別なし。ダブルクォートでくくった場合は書いたとおりの(つまり大文字と小文字が区別される)識別子となる。で、ダブルクォートでくくらない場合は大文字で書いたものとして扱う。というのが教科書的な説明。
しかし、そうでない実装が存在するので注意が必要。
次の環境で確認した。(いずれもWindows Vista Business上で稼動)

なお、MySQL v5.1 も試そうとしたのだが、ダブルクォートで括る形式の列名指定ができないので省略。
まずテーブル定義。

-- 大文字・小文字、ダブルクォートで括る・括らない
CREATE TABLE hoge(
    id VARCHAR(8),
    val1 INT,
    VAL2 INT,
    "val3" INT,
    "VAL4" INT
) ;
-- 試行する列名指定のパターン
INSERT INTO hoge(id) VALUES ('val1') ;
INSERT INTO hoge(id) VALUES ('val2') ;
INSERT INTO hoge(id) VALUES ('val3') ;
INSERT INTO hoge(id) VALUES ('val4') ;
INSERT INTO hoge(id) VALUES ('VAL1') ;
INSERT INTO hoge(id) VALUES ('VAL2') ;
INSERT INTO hoge(id) VALUES ('VAL3') ;
INSERT INTO hoge(id) VALUES ('VAL4') ;
INSERT INTO hoge(id) VALUES ('"val1"') ;
INSERT INTO hoge(id) VALUES ('"val2"') ;
INSERT INTO hoge(id) VALUES ('"val3"') ;
INSERT INTO hoge(id) VALUES ('"val4"') ;
INSERT INTO hoge(id) VALUES ('"VAL1"') ;
INSERT INTO hoge(id) VALUES ('"VAL2"') ;
INSERT INTO hoge(id) VALUES ('"VAL3"') ;
INSERT INTO hoge(id) VALUES ('"VAL4"') ;

で、試行。

-- 試行結果の記録。
-- 指定した列が存在したら、テーブル log に列名指定のパターンが記録される。
CREATE TABLE log(id VARCHAR(8), val INT) ;
INSERT INTO log(id, val) SELECT id, val1   FROM hoge WHERE id = 'val1' ;
INSERT INTO log(id, val) SELECT id, VAL1   FROM hoge WHERE id = 'VAL1' ;
INSERT INTO log(id, val) SELECT id, "val1" FROM hoge WHERE id = '"val1"' ;
INSERT INTO log(id, val) SELECT id, "VAL1" FROM hoge WHERE id = '"VAL1"' ;
INSERT INTO log(id, val) SELECT id, val2   FROM hoge WHERE id = 'val2' ;
INSERT INTO log(id, val) SELECT id, VAL2   FROM hoge WHERE id = 'VAL2' ;
INSERT INTO log(id, val) SELECT id, "val2" FROM hoge WHERE id = '"val2"' ;
INSERT INTO log(id, val) SELECT id, "VAL2" FROM hoge WHERE id = '"VAL2"' ;
INSERT INTO log(id, val) SELECT id, val3   FROM hoge WHERE id = 'val3' ;
INSERT INTO log(id, val) SELECT id, VAL3   FROM hoge WHERE id = 'VAL3' ;
INSERT INTO log(id, val) SELECT id, "val3" FROM hoge WHERE id = '"val3"' ;
INSERT INTO log(id, val) SELECT id, "VAL3" FROM hoge WHERE id = '"VAL3"' ;
INSERT INTO log(id, val) SELECT id, val4   FROM hoge WHERE id = 'val4' ;
INSERT INTO log(id, val) SELECT id, VAL4   FROM hoge WHERE id = 'VAL4' ;
INSERT INTO log(id, val) SELECT id, "val4" FROM hoge WHERE id = '"val4"' ;
INSERT INTO log(id, val) SELECT id, "VAL4" FROM hoge WHERE id = '"VAL4"' ;

-- テーブル log にあれば'O'、なければ'X'
SELECT hoge.id, 'O' AS result
    FROM hoge
    WHERE hoge.id IN (SELECT id FROM log)
UNION
SELECT hoge.id, 'X' AS result
    FROM hoge
    WHERE hoge.id NOT IN (SELECT id FROM log)
;

で、実行結果を集計したものが次の表。

対象列 列名指定 DB2 Oracle PostgreSQL Firebird
val1 val1 O O O O
VAL1 O O O O
"val1" X X O X
"VAL1" O O X O
VAL2 val2 O O O O
VAL2 O O O O
"val2" X X O X
"VAL2" O O X O
"val3" val3 X X O X
VAL3 X X O X
"val3" O O O O
"VAL3" X X X X
"VAL4" val4 O O X O
VAL4 O O X O
"val4" X X X X
"VAL4" O O O O

PostgreSQLのみ、ダブルクォートで括らない場合に小文字で書いたものとして扱う。つまり、PostgreSQLでは、冒頭のCREATE TABLE文とINSERT文のケースではエラーになるということに。