【问题标题】:How to remove a condition from where clause, if specific value is null (using prepared statements)如果特定值为空,如何从 where 子句中删除条件(使用准备好的语句)
【发布时间】:2019-04-18 00:10:34
【问题描述】:

从请求中获取参数:

String city = request.getParameter("city");
int price = Integer.parseInt(request.getParameter("price").toString());
int guests ... etc
date init_date... etc
date end_date...etc
initDate = parse init_date with simpledateformater...etc
endDate = parse init_date with simpledateformater...etc

让我们准备一个这样的语句:

String getResult = "SELECT id_housing, name, description_short, price, 
photo FROM housing WHERE city = ? AND init_date <= ? AND end_date >= ? AND 
price = ? AND guests >= ?";

PreparedStatement stmt = con.prepareStatement(getResult);

stmt.setString(1, city);
stmt.setDate(2, new java.sql.Date(initDate.getTime()));
stmt.setDate(3, new java.sql.Date(endDate.getTime()));
stmt.setInt(4, price);
stmt.setInt(5, guests);
ResultSet rs = stmt.executeQuery();

问题是如果值为空,我如何删除城市或价格或 WHERE 子句之后的任何值。 例如,如果我的用户没有在城市输入文本上写任何文本,则 request.getParameter 将为空(或空字符串“”,我不知道)。在这种情况下,我想删除 city = ?来自准备好的语句的条件,因此查询将返回具有任何城市值的行)。

我试过了

WHERE city = IFNULL(? , *) AND ...

但是没有用。

【问题讨论】:

标签: java mysql servlets prepared-statement


【解决方案1】:

只要城市值为空时改变getResult String即可。像这样的:

if(city == null) {
   getResult = "SELECT id_housing, name, description_short, price, photo FROM housing AND init_date <= ? AND end_date >= ? AND price = ? AND guests >= ?";

【讨论】:

    【解决方案2】:

    不幸的是。对于这种情况,您需要单独查询。

    这是使用原始 JDBC 访问数据库通常不是一个好主意的原因之一。对于复杂的查询,您最终会得到一堆容易出错的逻辑,这些逻辑会构建并连接它们。 如果您没有很多这样的情况,那么只需使用两个不同的查询。

    但是,如果您继续遇到更多此类查询,那么有很多库可以帮助您处理从打开连接到安全执行查询的所有事情,而无需使用原始字符串构建不同的查询。 Jooqmybatis 浮现在脑海中。

    【讨论】:

    • 如果未定义城市,他不想只返回城市为空的行。他想返回任何城市的行,所以你只需从 where 子句中删除城市。
    【解决方案3】:
    String getResult = "SELECT id_housing, name, description_short, price, 
        photo FROM housing WHERE init_date <= ? AND end_date >= ? AND 
        price = ? AND guests >= ?";
    if(city != null && !city.isempty()){
        getResult += " AND city = ? "
    }
    
    PreparedStatement stmt = con.prepareStatement(getResult);
    if(city != null && !city.isempty()){
        stmt.setString(1, city);
    }
    

    【讨论】:

      【解决方案4】:

      实现此目的的一种方法是创建一个查询存根/模板,您可以在其中动态附加 WHERE 条件。您将绑定变量保存在映射中,该映射将变量索引映射到相应的值:

      String queryStub = "SELECT id_housing, name, description_short, price, " 
          + "photo FROM housing WHERE 1=1";
      
      Map<Integer, Object> bindVariables = new HashMap<>();
      StringBuilder sb = new StringBuilder(queryStub);
      int paramIndex = 1;
      
      if (city != null && !city.isEmpty()) {
         sb.append(" AND city = ?")
         bindVariables.put(paramIndex++, city);
      }
      
      // ... handle the other, possibly empty inputs
      
      try (PreparedStatement stmt = con.prepareStatement(sb.toString());) {
      
          for (Map.Entry<Integer, Object> e : bindVariables.entrySet()) {
              stmt.setObject(e.getKey(), e.getValue());
          }
      
          ResultSet rs = stmt.executeQuery();
          // ...
      } 
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-04-21
        • 1970-01-01
        • 2021-09-19
        • 2016-05-06
        • 1970-01-01
        • 2015-03-16
        • 1970-01-01
        相关资源
        最近更新 更多