Параметризованный Oracle SQL-запрос в Java? - PullRequest
4 голосов
/ 10 августа 2010

Я пытался выяснить, почему следующий код не генерирует никаких данных в моем 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();

Тип данных для ШКОЛЫ - 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 говорит, что запрос SQL не меняется даже после setString или setCharacterStream. Я не уверен, что это потому, что установка параметров не работает или отладчик просто не может получить изменения в PreparedStatement.

Любая помощь будет принята с благодарностью, спасибо!

1 Ответ

9 голосов
/ 10 августа 2010

Я думаю, проблема в том, что ваш тип данных - 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();

Лучше всего использовать varchar вместо char, если ваши строки имеют гибкую длину. Тогда PreparedStatement будет работать как положено.

Обходным решением будет использование специфического для Oracle метода setFixedCHAR (но лучше, если возможно, изменить тип данных на varchar).

Следующее из Oracle PreparedStatement JavaDoc:


Данные CHAR в базе данных дополняются до ширины столбца. Это приводит к ограничению использования метода setCHAR () для привязки символьных данных к предложению WHERE инструкции SELECT - символьные данные в предложении WHERE также должны быть дополнены шириной столбца, чтобы обеспечить соответствие в операторе SELECT. Это особенно хлопотно, если вы не знаете ширину столбца.

setFixedCHAR () исправляет это. Этот метод выполняет сравнение без дополнения.

Примечания:

  • Не забудьте преобразовать подготовленный объект оператора в OraclePreparedStatement, чтобы использовать метод setFixedCHAR ().
  • Нет необходимости использовать setFixedCHAR () для оператора INSERT. База данных всегда автоматически дополняет данные до ширины столбца при вставке.

В следующем примере демонстрируется различие между методами 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
...