2015-11-02 2 views
0

У меня есть SQL выбрать с параметрами:Как построить sql-запрос со многими параметрами из java-кода?

SELECT * FROM tbl t WHERE t.name = ? AND t.age = ? AND t.number = ? AND ... AND t.last_parameter = ? order by t.some desc //many parameterss 

я получить параметры из полой формы и некоторые поля могут быть пустыми. Я строю SQL строку:

String sqlStatementText; 
     MessageFormat sqlStatementTextTemplate = new MessageFormat(Queries.WAR_GET_REPORT_COUNT); 
     List<Object> parametrs = new ArrayList<>(); 
     if (null == subscriberMSISDN || subscriberMSISDN.length() == 0) { 
      parametrs.add(""); 
     } else { 
      parametrs.add(Queries.WAR_REPORT_CALLING_NUMBER); 
     } 
     if (null == operatorID || operatorID.length() == 0) { 
      parametrs.add(""); 
     } else { 
      parametrs.add(Queries.WAR_REPORT_OPERATOR_AVAYA_ID); 
     } 
     if (null == operatorNickname || operatorNickname.length() == 0) { 
      parametrs.add(""); 
     } else { 
      parametrs.add(Queries.WAR_REPORT_NICKNAME); 
     } 
     if (null == msg1 || msg1.length() == 0) { 
      parametrs.add(""); 
     } else { 
      parametrs.add(Queries.WAR_REPORT_MSG1); 
     } 
     if (null == msg2 || msg2.length() == 0) { 
      parametrs.add(""); 
     } else { 
      parametrs.add(Queries.WAR_REPORT_MSG2); 
     } 
     sqlStatementText = sqlStatementTextTemplate.format(parametrs.toArray()); 

муравей их я это сделать:

try (Connection sqlConnection = connectionPool.getConnection(); 
      PreparedStatement sqlStatment = sqlConnection.prepareStatement(sqlStatementText)) { 
      int paramID = 1; 
      sqlStatment.setInt(paramID++, 1); 
      sqlStatment.setDate(paramID++, new java.sql.Date(fromDate.getTime())); 
      sqlStatment.setDate(paramID++, new java.sql.Date(toDate.getTime())); 
      if (null != subscriberMSISDN && subscriberMSISDN.length() != 0) { 
       sqlStatment.setString(paramID++, subscriberMSISDN); 
      } 
      if (null != operatorID && operatorID.length() != 0) { 
       sqlStatment.setString(paramID++, operatorID); 
      } 
      if (null != operatorNickname && operatorNickname.length() != 0) { 
       sqlStatment.setString(paramID++, operatorNickname); 
      } 
      if (null != msg1 && msg1.length() != 0) { 
       sqlStatment.setString(paramID++, msg1); 
      } 
      if (null != msg2 && msg2.length() != 0) { 
       sqlStatment.setString(paramID++, msg2); 
      } 
      try (ResultSet resultSet = sqlStatment.executeQuery()) { 
       while (resultSet.next()) { 
        count = resultSet.getInt(1); 
       } 
       resultSet.close(); 
       sqlStatment.close(); 
       sqlConnection.close(); 
      } 

Но я Thig это не правильно. Но я не знаю, как построить sql-запрос со многими параметрами, и если некоторые параметры могут быть пустыми.

+0

Можете ли вы внести изменения в свой sqlStatementText? если да, то одним из способов решения проблемы является использование NVL в разделе WHERE ... select * from ... WHERE 1 = 1 AND col1 = nvl (prm1, col1). в этом случае ваш существующий подход должен работать без изменений – are

ответ

0
  1. Перейдите на ORM. Они будут иметь форму criteria-подобный объект.
  2. Использовать синтаксис param - null или column = param SQL. select x from y where (? is null OR column1 = ?) Вам нужно установить значение параметра дважды, а значение ввода не может быть законным.
0

Невозможно это сделать, учитывая имеющуюся у вас инструкцию SQL.

Вам необходимо изменить условия SQL-оператора WHERE из таких вещей, как t.name = ?, t.name = nvl(?, t.name). Затем вы можете связать NULL там, и условие всегда будет оцениваться до true (поэтому он не действует как фильтр - это то, что вы хотите, когда пользователь покидает поле пустым).

Или - лучший подход, если вы можете это сделать, еще лучше использовать такие условия, как у вас есть (например, t.name= ?), но динамически строить условия в зависимости от того, какие поля вы дадите вам. То есть, например, если пользователь оставляет параметр «имя» пустым, просто опустите условие t.name = ? полностью.

Это дает вам более короткий оператор SQL, который упрощает работу оптимизатора Oracle. С подходом t.name = nvl(?, t.name), который я дал вам выше, вы полагаетесь на некоторые довольно продвинутые функции оптимизатора, чтобы получить максимальную производительность, потому что сразу не ясно, будет ли полезно или плохо для оптимизатора использовать индекс на t.name.

Смежные вопросы