資格試験の手続きが面倒…
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
うーん、注意が必要ですね。