SQL动态查询是指根据运行时传入的参数动态生成SQL语句的技术,主要用于处理查询条件不固定的业务场景,比如用户可以根据姓名、年龄、部门等多个可选条件自由组合筛选数据。

一、数据库原生动态SQL实现
很多关系型数据库都支持原生动态SQL,以MySQL为例,可以通过PREPARE语句和EXECUTE语句实现动态SQL的拼接和执行。
1.1 MySQL原生动态SQL示例
下面的示例根据传入的姓名和年龄参数动态拼接查询语句:
-- 声明变量存储动态SQL和参数
SET @sql = 'SELECT * FROM user WHERE 1=1';
SET @name_param = '张三';
SET @age_param = 25;
-- 动态拼接条件
IF @name_param IS NOT NULL THEN
SET @sql = CONCAT(@sql, ' AND name = ''', @name_param, '''');
END IF;
IF @age_param IS NOT NULL THEN
SET @sql = CONCAT(@sql, ' AND age = ', @age_param);
END IF;
-- 预处理并执行
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;1.2 注意事项
原生动态SQL拼接时直接拼接字符串容易引发SQL注入风险,因此如果要使用原生动态SQL,建议尽量使用参数化查询,避免直接将用户输入拼接到SQL语句中。
二、存储过程中的动态SQL
存储过程也可以实现动态SQL,适合将复杂的查询逻辑封装在数据库端。以Oracle的存储过程为例,可以通过EXECUTE IMMEDIATE执行动态SQL。
CREATE OR REPLACE PROCEDURE query_user(
p_name IN VARCHAR2,
p_age IN NUMBER,
p_cursor OUT SYS_REFCURSOR
) AS
v_sql VARCHAR2(1000) := 'SELECT * FROM user WHERE 1=1';
BEGIN
IF p_name IS NOT NULL THEN
v_sql := v_sql || ' AND name = :name';
END IF;
IF p_age IS NOT NULL THEN
v_sql := v_sql || ' AND age = :age';
END IF;
-- 使用参数化执行动态SQL
IF p_name IS NOT NULL AND p_age IS NOT NULL THEN
OPEN p_cursor FOR v_sql USING p_name, p_age;
ELSIF p_name IS NOT NULL THEN
OPEN p_cursor FOR v_sql USING p_name;
ELSIF p_age IS NOT NULL THEN
OPEN p_cursor FOR v_sql USING p_age;
ELSE
OPEN p_cursor FOR v_sql;
END IF;
END query_user;三、ORM框架中的动态SQL实现
日常开发中更常用的是ORM框架提供的动态SQL能力,比如MyBatis就提供了丰富的动态SQL标签,避免手动拼接字符串的问题。
3.1 MyBatis动态SQL示例
MyBatis通过if、choose、where等标签实现动态SQL,下面的示例实现用户多条件查询:
<select id="queryUser" parameterType="map" resultType="User">
SELECT * FROM user
<where>
<if test="name != null and name != ''">
AND name = #{name}
</if>
<if test="age != null">
AND age = #{age}
</if>
<if test="deptId != null">
AND dept_id = #{deptId}
</if>
</where>
</select>where标签会自动处理条件开头的AND或者OR,避免拼接出WHERE AND name = ?这种错误语法。
3.2 其他常用动态标签
choose、when、otherwise:实现类似Java中switch-case的逻辑,多个条件中选择一个生效foreach:用于遍历集合参数,实现IN查询等场景trim:可以自定义去除SQL片段开头或结尾的指定字符
四、动态SQL编写的核心注意事项
4.1 防范SQL注入
无论使用哪种方式实现动态SQL,都要避免直接将用户输入的内容拼接到SQL字符串中,优先使用参数化查询,ORM框架中要使用#{}而非${}来接收参数。
4.2 性能优化
动态SQL拼接时尽量保持SQL的结构稳定,避免频繁生成完全不同的SQL语句导致数据库无法复用执行计划,同时不要在动态条件中包含无意义的1=1这类冗余条件,可以使用where标签自动处理条件拼接。
4.3 可读性维护
动态SQL逻辑不要过于复杂,如果条件组合过多,可以适当拆分不同的查询方法,避免单个动态SQL逻辑过于冗长难以维护。
动态SQLSQL动态查询存储过程MyBatis动态SQLSQL拼接修改时间:2026-06-07 00:45:33