温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

动态SQL如何实现

发布时间:2026-07-14 08:23:11 来源:亿速云 阅读:87 作者:小樊 栏目:数据库

动态 SQL 指的是在运行时根据条件动态拼接 SQL 语句,而不是在代码中写死 SQL。它常见于 MyBatisJDBC + 字符串拼接Spring JDBC 等场景。下面以 MyBatis 为主进行说明(最常用),并补充其他实现方式。


一、为什么需要动态 SQL?

实际业务中 SQL 条件往往不确定,例如:

  • 查询用户:可能按姓名、年龄、状态查询
  • 条件可为空,不能写死 where name = ? and age = ?

二、MyBatis 中的动态 SQL(重点)

MyBatis 提供了 XML 标签 来实现动态 SQL。

1️⃣ <if> 判断条件

<select id="selectUser" resultType="User">
  SELECT * FROM user
  WHERE 1=1
  <if test="name != null">
    AND name = #{name}
  </if>
  <if test="age != null">
    AND age = #{age}
  </if>
</select>

✅ 只有条件不为空时才会拼接 SQL


2️⃣ <where> 自动处理 AND / OR

避免手写 1=1

<select id="selectUser" resultType="User">
  SELECT * FROM user
  <where>
    <if test="name != null">
      AND name = #{name}
    </if>
    <if test="age != null">
      AND age = #{age}
    </if>
  </where>
</select>

<where> 会自动去掉多余的 AND / OR


3️⃣ <choose> / <when> / <otherwise>(类似 switch)

<select id="selectUser" resultType="User">
  SELECT * FROM user
  <where>
    <choose>
      <when test="type == 'A'">
        AND type = 'A'
      </when>
      <when test="type == 'B'">
        AND type = 'B'
      </when>
      <otherwise>
        AND status = 1
      </otherwise>
    </choose>
  </where>
</select>

4️⃣ <foreach> 用于 IN 查询

<select id="selectByIds" resultType="User">
  SELECT * FROM user
  WHERE id IN
  <foreach collection="ids" item="id" open="(" close=")" separator=",">
    #{id}
  </foreach>
</select>

调用:

List<Integer> ids = Arrays.asList(1,2,3);

生成 SQL:

SELECT * FROM user WHERE id IN (1,2,3)

5️⃣ <set> 动态更新字段

<update id="updateUser">
  UPDATE user
  <set>
    <if test="name != null">name = #{name},</if>
    <if test="age != null">age = #{age},</if>
  </set>
  WHERE id = #{id}
</update>

✅ 自动去掉多余逗号


6️⃣ <trim> 自定义拼接规则(高级)

<trim prefix="WHERE" prefixOverrides="AND | OR">
  <if test="name != null">
    AND name = #{name}
  </if>
</trim>

三、MyBatis 注解方式(不推荐复杂 SQL)

@Select("<script>" +
        "SELECT * FROM user" +
        "<where>" +
        "  <if test='name != null'>AND name = #{name}</if>" +
        "</where>" +
        "</script>")
List<User> selectUser(@Param("name") String name);

四、JDBC 原生方式(不推荐)

String sql = "SELECT * FROM user WHERE 1=1";
if (name != null) {
    sql += " AND name = '" + name + "'";
}

SQL 注入风险 ✅ 实际项目中不建议使用


五、Spring JDBC(JdbcTemplate)

StringBuilder sql = new StringBuilder("SELECT * FROM user WHERE 1=1");
List<Object> params = new ArrayList<>();

if (name != null) {
    sql.append(" AND name = ?");
    params.add(name);
}

六、动态 SQL 的常见问题

❗ SQL 注入

  • 正确:使用 #{}(预编译)
  • 错误:使用 ${}(字符串替换)

❗ 性能

  • 避免无索引条件
  • 避免 if 过多导致 SQL 复杂

七、总结

方式 推荐度 说明
MyBatis XML ⭐⭐⭐⭐⭐ 最常用、最安全
MyBatis 注解 ⭐⭐⭐ 简单 SQL
JDBC 拼接 不安全
Spring JDBC ⭐⭐⭐ 中等复杂度

如果你愿意,我可以:

  • 给你一个 完整 MyBatis 动态 SQL 示例
  • 对比 MyBatis vs JPA 动态查询
  • 动态 SQL 执行原理

你更想了解哪一种?

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI