首页 > 解决方案 > 使用可选的 from 和 to 日期构建 SQL where 子句

问题描述

我正在寻找最短的if语句(或其他东西)来构建允许各种情况的 SQL 查询:

  1. 给定 'from' 日期,没有 'to' 日期,
  2. 给定'to'日期,没有'from'日期,
  3. 给定 'from' 和 'to' 日期,
  4. 没有“从”或“到”日期。

缺少“从”或“到”日期意味着空值。根据语句的输出,特定where子句将动态添加到类型化查询中。

我可以用一个嵌套来解决它​​,if但它看起来很难看。有什么建议么?

标签: javasql

解决方案


创建 SQL 语句时,您不仅有查询字符串,还有准备好的变量。您需要同时添加它们。就像是:

StringBuilder sql = new StringBuilder();
List<Object> variables = new ArrayList<>();

sql.append("SELECT <columns> FROM <tables> WHERE 1");

if (fromDate != null) {
    sql.append(" AND date >= ?");
    variables.add(fromDate);
}

if (toDate != null) {
    sql.append(" AND date <= ?");
    variables.add(toDate);
}
PreparedStatement statement = connection.prepareStatement(sql.toString());

for (int i = 0; i < variables.size(); i++) {
    statement.setObject(i + 1, variables.get(i));
}

手动执行此操作很痛苦,尤其是当您开始混合ANDOR使用括号时。考虑使用一个可以处理繁琐工作的 SQL 库。我可以为jOOQ担保:

动态构造在WHERE子句的情况下特别有用,用于动态谓词构造。例如:

public Condition condition(HttpServletRequest request) {
    Condition result = trueCondition();
    
    if (request.getParameter("title") != null)
        result = result.and(BOOK.TITLE.like("%" + request.getParameter("title") + "%"));
        
    if (request.getParameter("author") != null)
        result = result.and(BOOK.AUTHOR_ID.in(
            selectOne().from(AUTHOR).where(
                    AUTHOR.FIRST_NAME.like("%" + request.getParameter("author") + "%")
                .or(AUTHOR.LAST_NAME .like("%" + request.getParameter("author") + "%"))
            )
        ));
    
    return result;
}

// And then:
create.select()
      .from(BOOK)
      .where(condition(httpRequest))
      .fetch();

推荐阅读