动态 SQL(Dynamic SQL) 通常指 在运行时才确定最终要执行的 SQL 语句,而不是在写代码时就写死。它常见于 MyBatis、JDBC、存储过程、ORM 框架 中。下面我按 使用场景 + 示例 给你讲清楚。
✅ 静态 SQL:SQL 在编译期就固定了
SELECT * FROM user WHERE id = 1;
✅ 动态 SQL:SQL 根据条件、参数、状态在运行时拼接
SELECT * FROM user WHERE 1=1
<if test="name != null">
AND name = #{name}
</if>
<if> 条件判断<select id="findUser" 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>
✅ 如果 name 为空,就不会拼 AND name = ?
<choose> / <when> / <otherwise>(类似 switch)<select id="findUser" resultType="User">
SELECT * FROM user
WHERE 1=1
<choose>
<when test="type == 'A'">
AND type = 'A'
</when>
<when test="type == 'B'">
AND type = 'B'
</when>
<otherwise>
AND type = 'C'
</otherwise>
</choose>
</select>
<where> 自动处理 AND / OR<select id="findUser" resultType="User">
SELECT * FROM user
<where>
<if test="name != null">
AND name = #{name}
</if>
<if test="age != null">
AND age = #{age}
</if>
</where>
</select>
✅ 自动去掉多余的 AND
✅ 如果条件为空,不会生成 WHERE
<set> 用于 UPDATE<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>
✅ 自动去掉末尾多余的 ,
<foreach> 遍历集合(IN 查询)<select id="findByIds" 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)
String sql = "SELECT * FROM user WHERE 1=1";
if (name != null) {
sql += " AND name = '" + name + "'";
}
⚠️ 缺点
✅ 正确方式(PreparedStatement):
String sql = "SELECT * FROM user WHERE 1=1";
if (name != null) {
sql += " AND name = ?";
}
SET @sql = 'SELECT * FROM user WHERE 1=1';
IF name IS NOT NULL THEN
SET @sql = CONCAT(@sql, ' AND name = ''', name, '''');
END IF;
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
✅ 适合:
❌ 不适合:
SQL 注入
#{} 而不是 ${}${} 和 #{} 区别
#{}:预编译 ✅${}:直接替换 ❌(只能用于表名/排序)性能
动态 SQL = 根据条件在运行时拼 SQL,MyBatis 是最常用、最安全的实现方式
如果你愿意,我可以:
你现在是 MyBatis / JDBC / 存储过程 哪种场景?
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。