Подготовленный оператор - использование функции как части предложения where - PullRequest
0 голосов
/ 05 октября 2009

Я работаю с подготовленным оператором Java, который получает данные из базы данных Oracle. Из-за некоторых проблем с производительностью запрос использует «виртуальный столбец» в качестве индекса.

Запрос выглядит так:

String status = "processed";
String customerId = 123;
String query = "SELECT DISTINCT trans_id FROM trans WHERE status = " + status + " AND FN_GET_CUST_ID(trans.trans_id) = " + customerId;

Connection conn = getConnection();
PreparedStatement ps = null;
ResultSet rs = null;

try {
  ps = conn.prepareStatement(query);
  ps.execute();
  ...
} catch (...)

Это не работает. Наличие функции как части предложения where вызывает исключение SQLException. Я знаю о CallableStatement и знаю, что могу сначала использовать это, а затем объединить результаты. Однако эта таблица использует FN_GET_CUST_ID (trans_id) как часть своего индекса. Есть ли способ использовать подготовленный оператор с функцией базы данных в качестве параметра запроса?

Ответы [ 3 ]

6 голосов
/ 05 октября 2009
  1. Никогда не объединяйте аргументы для SQL в строку. Всегда используйте заполнители (?) и setXxx(column, value);.

  2. Вы получите ту же ошибку, если будете запускать SQL в своем любимом инструменте БД. Проблема в том, что Oracle по какой-то причине не может использовать эту функцию. Какой код ошибки вы получаете?

1 голос
/ 05 октября 2009

Если идентификатор клиента числовой, оставьте его в int, а не в String. Затем попробуйте сделать следующее:

String query = "SELECT DISTINCT trans_id FROM trans WHERE status = ? AND FN_GET_CUST_ID(trans.trans_id) = ?"; 

ps = conn.prepareStatement(query); 
ps.setString(1, status);
ps.setInt(2, customerId);
ps.execute();

Помимо других преимуществ подготовленного оператора, вам не нужно помнить о строковых кавычках (это, скорее всего, приводит к вашей ошибке) и экранировании специальных символов.

0 голосов
/ 05 октября 2009

На первый взгляд запрос кажется неверным. Вы пропускаете апостроф до и после использования переменной status (при условии, что статус является столбцом varchar).

String query = "SELECT DISTINCT trans_id FROM trans 
WHERE status = '" + status + "' AND FN_GET_CUST_ID(trans.trans_id) = " + customerId;

РЕДАКТИРОВАТЬ: я не из Java происхождения. Однако, как сказал @Aron, лучше использовать заполнители, а затем использовать какой-либо метод для установки значений параметров, чтобы избежать SQL-инъекций .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...