SQL多条件动态查询_动态SQL构建方法

动态sql多条件查询的核心是只拼接用户实际输入的有效条件,避免空值或默认值参与where过滤;常用mybatis的标签配合处理and逻辑,或用case when实现纯sql条件分支,同时需规范前端传参清洗与后端校验,并推荐使用querywrapper等构建器模式提升安全性与可维护性。

SQL多条件动态查询_动态SQL构建方法

动态SQL多条件查询的核心是:只拼接用户实际输入的条件,避免空值或默认值参与WHERE过滤,防止查出错误数据或全表扫描。

用IF判断拼接条件(MyBatis示例)

MyBatis中常用标签控制条件是否加入SQL。关键点是每个条件独立判断,且注意AND位置——统一前置AND,用自动处理首条件无AND的问题。

  • 用户名不为空才加AND user_name LIKE CONCAT('%', #{userName}, '%')
  • 状态为有效值(如0/1)才加AND status = #{status},避免传入null或-1时误匹配
  • 时间范围需同时校验开始和结束时间,仅一个有值时按单边查询处理

用CASE WHEN做条件分支(纯SQL写法)

在存储过程或视图中,可用CASE WHEN配合参数做逻辑路由。例如:

SELECT * FROM order WHERE
  status = CASE WHEN #{status} IS NOT NULL THEN #{status} ELSE status END
  AND (#{startTime} IS NULL OR create_time >= #{startTime})
  AND (#{endTime} IS NULL OR create_time

这种写法不拼SQL,但需注意:数据库仍可能因参数为NULL跳过索引,建议配合函数索引或改用动态拼接。

避免常见坑:空字符串、0、NULL混用

前端传参常把未填项发成空字符串””或数字0,后端要提前清洗:

  • 字符串类型:trim后判空,””和” ”(中文空格)都应视为无效
  • 数值类型:0可能是合法值(如“未评分”),需约定特殊标记(如-999)表示“不筛选”
  • 日期类型:不能直接用#{date} != null,Java里String转Date失败会抛异常,应先校验格式再传参

用构建器模式封装(Java推荐)

用QueryWrapper(MyBatis-Plus)或自定义CriteriaBuilder,让代码可读性更强:

QueryWrapper wrapper = new QueryWrapper();
if (StringUtils.isNotBlank(req.getName())) {
  wrapper.like(“user_name”, req.getName());
}
if (req.getStatus() != null && req.getStatus() >= 0) {
  wrapper.eq(“status”, req.getStatus());
}
userMapper.selectList(wrapper);

这种方式天然规避SQL注入,逻辑清晰,扩展新增条件只需加一行if。