- PR -

PreparedStatementについて

投稿者投稿内容
taku
ぬし
会議室デビュー日: 2002/11/12
投稿数: 918
お住まい・勤務地: 墨田区→中野区
投稿日時: 2004-02-12 21:01
引用:

いっぱいいっぱいさんの書き込み (2004-02-12 20:56) より:
「条件にマッチしていない」と仰られているのは、例えば「user_id」に
設定される値が実際には、DBに無いような場合を仰られているのでしょうか?


 そうです。

引用:

そのような場合も、SQL的には、Exceptionを発生させるのではないでしょうか?


 正しいSQL文を実行して例外が投げられることはありません。
raystar
ぬし
会議室デビュー日: 2003/01/16
投稿数: 251
お住まい・勤務地: Tokyo/Japan
投稿日時: 2004-02-12 21:52
where句の user_id = ?で
更新レコードがなかっただけでは?

変数の値を確認するとわかると思います。
いっぱいいっぱい
会議室デビュー日: 2004/02/12
投稿数: 8
投稿日時: 2004-02-12 22:16
ご指摘まことに有難うございました。
非常にお騒がせしてしまいまして、まことに申し訳ございません。。。

原因はどうやら、変数"user_id"にあったようです。
このuser_idには、DB上の"USERID"という列に格納されている
いずれかの値が入るのですが、このUSERID列は、CHAR型の16桁となっております。

しかし、変数"user_id"の中身の値は16桁に満たない値が入っていたために
条件にマッチしなかった可能性が高いです。。。

このような時は、CHAR型→VARCHAR型への変更をせざるを得ないのでしょうか。。。(^^;
ゆう
ベテラン
会議室デビュー日: 2003/06/20
投稿数: 56
投稿日時: 2004-02-13 08:52
こんにちわ。

USERID列の値をTRIMしてからuser_idとマッチさせるか、
user_idが16桁になるように空白でPADDINGしてからマッチさせてはいかがですか?
#USERID列の16桁に満たない部分が空白で埋まっていると仮定していますが…
taku
ぬし
会議室デビュー日: 2002/11/12
投稿数: 918
お住まい・勤務地: 墨田区→中野区
投稿日時: 2004-02-13 09:35
引用:

ゆうさんの書き込み (2004-02-13 08:52) より:
こんにちわ。

USERID列の値をTRIMしてからuser_idとマッチさせるか、
user_idが16桁になるように空白でPADDINGしてからマッチさせてはいかがですか?
#USERID列の16桁に満たない部分が空白で埋まっていると仮定していますが…


 TRIMをかけてしまうとインデックスが働かなくなると思いますので、
足らない桁数だけ空白埋めしたほうがよいかと思われます。

 まあ、この手のテーブルは件数がそれほど多く無いと思われるので、
体感速度は変らないでしょうけど。
ゆう
ベテラン
会議室デビュー日: 2003/06/20
投稿数: 56
投稿日時: 2004-02-13 11:54
こんにちわ。

引用:

takuさんの書き込み (2004-02-13 09:35) より:

 TRIMをかけてしまうとインデックスが働かなくなると思いますので、
足らない桁数だけ空白埋めしたほうがよいかと思われます。




たしかにUSERIDなんていう名前のカラムはINDEXが張ってありそうですね…
そこまで考えてませんでした
というわけで、Indexを張っているならば
takuさんの仰るようにパディングしたほうがよさそうです。

[ メッセージ編集済み 編集者: ゆう 編集日時 2004-02-13 11:55 ]
いっぱいいっぱい
会議室デビュー日: 2004/02/12
投稿数: 8
投稿日時: 2004-02-13 14:30
takuさん、ゆうさん、ご回答どうも有難うございます!

>TRIMをかけてしまうとインデックスが働かなくなると思いますので、
>足らない桁数だけ空白埋めしたほうがよいかと思われます。

上記は、「PreparedStatementを使用しているActionの中で、変数user_idを取得した
際に16桁に満たない部分は、空白を埋めてしまう」という意味ですよね?

じつは、PreparedStatementを使用する前は、普通のStatementを使用して
以下のようなコードにしておりました。

Statement stmt = con.createStatement();
String sql = "UPDATE ZRDBB01Z SET";
sql = sql + " PASSWD='" + hash_pass + "'";
sql = sql + " where (userid='" + user_id +"')";
        int result = stmt.executeUpdate(sql);

上記のStatementを使用していた際には、変数user_idに16桁以内の値が入った時でも
問題なく動作しておりました。(Statementは自動で、足りない空白を埋めてくれたりしてるんですかね?)

ただ、上記だと変数"hash_pass"に「'」が含まれる場合があり、その場合は
SQL文が壊れてしまい、SQLエラーとなる場合があります。

「'」が含まれた場合のエスケープ処理をPreparedStatementが自動で
行ってくれると聞きましたので、今回PreparedStatementを使用しようと
苦労している背景があったりします。
顔爺
ベテラン
会議室デビュー日: 2003/10/03
投稿数: 52
投稿日時: 2004-02-13 14:48
PreparedStatement の仕様です(少なくとも、Oracle JDBC 上では)。
「Oracle JDBC開発者ガイドおよびリファレンス リリース1(9.0.1)」(pdfファイル)の
6-17 ページ、「WHERE 句に CHAR データをバインドするためのメソッド、setFixedCHAR」
を参照してください。

### 以下、追記
当該ページを引用します。

> データベース内のCHAR データは、列幅まで埋め込まれます。このため、SELECT 文の
> WHERE 句に文字データをバインドするためのsetCHAR() メソッドの使用に関して、制限が
> 生じます。つまり、WHERE 句の文字データも、SELECT 文で合致させるために、列幅まで埋
> め込む必要があります。これは特に列幅がわからない場合に問題になります。
> これを修正するために、Oracle はOraclePreparedStatement クラスに
> setFixedCHAR() メソッドを追加しました。このメソッドは埋込みなしの比較を実行しま
す。

使用例
> ((OraclePreparedStatement)pstmt).setFixedCHAR(1, "JDBC");




[ メッセージ編集済み 編集者: 顔爺 編集日時 2004-02-13 14:57 ]

スキルアップ/キャリアアップ(JOB@IT)