5

次のコードがResultSetにデータを生成しない理由を理解しようとしています。

String sql = "SELECT STUDENT FROM SCHOOL WHERE SCHOOL = ? ";
PreparedStatement prepStmt = conn.prepareStatement(sql);
prepStmt.setString(1, "Waterloo");
ResultSet rs = prepStmt.executeQuery();

一方、以下は正しく実行されます。

String sql = "SELECT STUDENT FROM SCHOOL WHERE SCHOOL = 'Waterloo' ";
PreparedStatement prepStmt = conn.prepareStatement(sql);
ResultSet rs = prepStmt.executeQuery();

SCHOOLのデータ型はCHAR(9バイト)です。setStringの代わりに、次のことも試しました。

String sql = "SELECT STUDENT FROM SCHOOL WHERE SCHOOL = ? ";
PreparedStatement prepStmt = conn.prepareStatement(sql);
String school = "Waterloo";
Reader reader = new CharArrayReader(school.toCharArray());
prepStmt.setCharacterStream(1, reader, 9);
prepStmt.setString(1, "Waterloo");
ResultSet rs = prepStmt.executeQuery();

私は次に何を調査するかについて完全に立ち往生しています。Eclipseデバッガーは、setStringまたはsetCharacterStreamの後でもSQLクエリは変更されないと言います。パラメータの設定が機能していないことが原因なのか、それともデバッガがPreparedStatementの変更を取得できないだけなのかはわかりません。

どんな助けでも大歓迎です、ありがとう!

4

1 に答える 1

10

問題は、データ型がCHAR(9)であり、「Waterloo」の文字数が8文字しかないことだと思います。これにより、期待される結果(LIKEおよび%)が返されると思います。または、不足しているスペースを追加します。

String sql = "SELECT STUDENT FROM SCHOOL WHERE SCHOOL LIKE ? ";
PreparedStatement prepStmt = conn.prepareStatement(sql);
prepStmt.setString(1, "Waterloo%");
ResultSet rs = prepStmt.executeQuery();

文字列の長さが柔軟な場合は、charの代わりにvarcharを使用するのが最善の方法です。その後、PreparedStatementは期待どおりに機能します。

回避策は、Oracle固有のsetFixedCHARメソッドを使用することです(ただし、可能であれば、データ型をvarcharに変更することをお勧めします)。

以下は、OracleのPreparedStatementJavaDocからのものです。


データベース内のCHARデータは、列幅に埋め込まれます。これにより、setCHAR()メソッドを使用して文字データをSELECTステートメントのWHERE句にバインドする際の制限が発生します。SELECTステートメントで一致を生成するには、WHERE句の文字データも列幅にパディングする必要があります。列幅がわからない場合、これは特に厄介です。

setFixedCHAR()はこれを修正します。このメソッドは、埋め込みなしの比較を実行します。

ノート:

  • setFixedCHAR()メソッドを使用するには、プリペアドステートメントオブジェクトをOraclePreparedStatementにキャストすることを忘れないでください。
  • INSERTステートメントにsetFixedCHAR()を使用する必要はありません。データベースは、データを挿入するときに、常にデータを列幅に自動的に埋め込みます。

次の例は、setString()、setCHAR()、およびsetFixedCHAR()メソッドの違いを示しています。

// Schema is : create table my_table (col1 char(10));
//             insert into my_table values ('JDBC');
PreparedStatement pstmt = conn.prepareStatement
("select count() from my_table where col1 = ?");
ResultSet rs;

pstmt.setString (1, "JDBC");  // Set the Bind Value
rs = pstmt.executeQuery();    // This does not match any row
// ... do something with rs
CHAR ch = new CHAR("JDBC      ", null);
((OraclePreparedStatement)pstmt).setCHAR(1, ch); // Pad it to 10 bytes
rs = pstmt.executeQuery();     // This matches one row
// ... do something with rs
((OraclePreparedStatement)pstmt).setFixedCHAR(1, "JDBC");
rs = pstmt.executeQuery();     // This matches one row
// ... do something with rs
于 2010-08-10T16:59:04.793 に答える