CHARとVARCHAR2を比較するときは下記のサイトにあるようなことに注意する必要がある。
CHAR と VARCHAR2 の違い - オラクル・Oracleをマスターするための基本と仕組み
ところで上のサイトなど非空白埋め比較セマンティクスを紹介しているところでは、CHARがその長さよりも短い文字列しか入ってなかったケースについては書いてないように思う。とはいってもまぁ、固定長文字列にその長さより短い文字列をいれることは少ないからなんだろうけど、非空白埋め比較セマンティクスなのにまるで空白埋めされるかのような動作にはまってしまった。そのハマりどころについてメモする。
まず、CHARとVARCHAR2をそれぞれ持つ適当なテーブルを2つ作る。
CREATE TABLE TABLE_CHAR (COLUMN1 CHAR(8) ); CREATE TABLE TABLE_VARCHAR2 (COLUMN1 VARCHAR2(20) );
データを入れる。CHARのテーブルの方には、サイズ8に対して4バイトの文字列を挿入している点に注意。
INSERT INTO TABLE_CHAR (COLUMN1) VALUES ('AAAA'); INSERT INTO TABLE_VARCHAR2 (COLUMN1) VALUES ('AAAA');
それで、下記のSQLを実行するとどうなるか。
SELECT * FROM table_char t1, table_varchar2 t2 WHERE t1.column1 = t2.column1;
これはゼロ件になる。落ち着いて考えれば、CHARは固定長文字列なので、'AAAA'は'AAAA____'(_は空白)として格納されているので、比較すれば不一致になるのは当然である。
実際、下記のようなクエリを実行すると一致する。
SELECT * FROM table_char t1, table_varchar2 t2 WHERE t1.column1 = t2.column1||' ';
まるでCHAR型の方が空白埋めされているかのように見えてしまい、誠に混乱した次第です。わかってしまえばなんてことないのだが、開発しているときには態々すでにあるテーブルの型は調べないので、気付くまでに時間がかかってしまった。