No Programming, No Life

プログラミング関連の話題や雑記

資格試験の手続きが面倒…

SunがやってるJavaの資格試験を受けようと思ったんですが、
オンラインでちゃちゃっと予約できるかと思ったら
そんなに簡単ではありませんでした。

XMLマスターの資格をとったときはR-PROMETRIC
結構簡単に予約できたんだけど、
今回はバウチャーチケットなるものを
事前に購入しておかないとダメらしくて
ちょっと面倒です。

で、R-PROMETRICでバウチャーチケットが買えるのかな〜と
思ったら買える一覧に入ってなくて、しょうがないから
Sunのページを見に行ったらやっと買えそうな感じのページがありました。

しかし、振込先がいかにもって感じの「アメリカ銀行 東京支店」
ん〜〜、なんか怖いなぁ…受験料も\ 24,000 (税込 \ 25,200)もするしなぁ。
ちょっと時間のあるときに詳しく見てみるか。

日付フォーマットエラー

今私が仕事で作っているとあるシステムで、
エラーが発生しました。

ブラウザ上のINPUTフィールドに入力された
日付フォーマット文字列を
そのままSQLに投げる部分でこのエラーが発生した模様です。

ORA-01847: 月単位の日付は1から月末日の間で指定する必要があります

さて、このOracleのエラーが発生したわけですが、
これはたとえば "2006/5/32" とかみたいな
ありえない日付を入力されたときに起こるエラーです。

ところで今作っている日付フォーマットチェックは完璧にされているはずなんですが
どうしてこんなことが起こったんだろう?
データ受け渡しのBeanの詰め替えが失敗しているのかな?
ということでソースコードをひたすら追いかけていってみたら
以下のような部分を発見しました。

/* 作成日(To) */
str = bean.getSishkshnToDt();
if (str != null && false == str.equals("")) {
	list.add(str + "23:59:59.999999999"); //作成日(To)
}

SQLのWHERE部分

str = bean.getSishkshnToDt();
if (str != null && false == str.equals("")) {
	conditionBuff.append(" AND b.sishkshn_dt <= TO_TIMESTAMP(?,'YYYY/MM/DDHH24:MI:SSxFF')"); //作成日(To)
}

beanの項目sishkshnToDtに "23:59:59.999999999" を結合した文字列を
SQLのパラメータとして作成している部分なんですが、
これではまずいことに気が付きます。
もし、strの中身が"2006/5/3"のような日付だった場合、
結合した文字列は
"2006/5/323:59:59.999999999"となってしまい
これで晴れて"2006/5/32"という
無茶な日付が完成します。

回避作として以下のようにするといいみたいです。

list.add(str + " 23:59:59.999999999"); //作成日(To)

のように23の前に半角スペースを入れてあげると
Oracleさんはちゃんと動いてくれるみたいです。

このエラーの原因は日付フォーマットチェックを行った後に
文字列を結合してしまっている点にあります。
エラーチェックの際の順番は大事ですね。

Oracleの列名のダブルクォート

テスト用にまだ追加されてないテーブルを
ローカルでちゃちゃっと作成することになったんですが、
これまでCREATE TABLE文を使ったことがなかった私は
典型的なミス(なのかな?)を犯してしまいました。

以下のようなCREATE TABLE文を実行

CREATE TABLE "TB_XXX"
(
    "ftkt_jgyb_cd" CHAR(2),
    "hst_nm"       VARCHAR2(255),
       :
       :
       :
);

で、こんな感じのSQLを実行してみたんですが…

SQL>
select ftkt_jgyb_cd from tb_xxx

SQLを実行中です...

SQL実行中に以下のエラーが発生しました。
ORA-00904: "FTKT_JGYB_CD": 無効な識別子です。

ん??項目名はぴったりあってるのになぁ…ちなみに

select * from tb_xxx

だとちゃんと取得できます。
何が問題なんだろうと思ってネットで調べてみたら
分かりました。

Oracle SQL では、ダブルクォート(")で囲まない英小文字は大文字に変換されて処理されます。ダブルクォート(")で囲んだ場合は、この変換は行われません。

Oracle雑記帳:☆ダブルクォート(")使用上の注意点

つまり、私がCREATEしたテーブルの項目名は
ダブルクォートで囲んでしまったために、
ダブルクォートで囲まないSQLを書いてしまうと
Oracleの方で勝手に大文字に変換してしまうので

select ftkt_jgyb_cd from tb_xxx

は勝手に

select FTKT_JGYB_CD from tb_xxx

と解釈されてしまうということですね。

実際にダブルクォートで囲ってみたら、うまく取得できました。

select "ftkt_jgyb_cd" from tb_xxx

うーん、注意が必要ですね。