温馨提示×

温馨提示×

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

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

如何手写Dynamic SQL

发布时间:2026-10-20 02:16:43 来源:亿速云 阅读:81 作者:小樊 栏目:数据库

“手写 Dynamic SQL”通常指不依赖 ORM 全自动生成 SQL,而是根据条件在代码中动态拼接 / 构造 SQL 语句。下面从思路、常见方式、示例、注意事项几个方面讲清楚。


一、Dynamic SQL 的核心思想

Dynamic SQL = SQL 不是写死的,而是根据运行时的条件变化

常见变化点:

  • 查询条件(WHERE)
  • 排序字段(ORDER BY)
  • 分页(LIMIT / OFFSET)
  • 插入字段(INSERT)
  • 更新字段(UPDATE)

二、手写 Dynamic SQL 的常见方式

1️⃣ 字符串拼接(最基础,但不安全)

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

❌ 问题:

  • SQL 注入
  • 引号转义麻烦
  • 难维护

2️⃣ 使用 PreparedStatement + 条件拼接(推荐)

✅ 安全、标准、可控

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);
}
if (age != null) {
    sql.append(" AND age > ?");
    params.add(age);
}

sql.append(" ORDER BY id DESC");

PreparedStatement ps = conn.prepareStatement(sql.toString());
for (int i = 0; i < params.size(); i++) {
    ps.setObject(i + 1, params.get(i));
}

✅ 优点:

  • 防 SQL 注入
  • 条件清晰
  • 易扩展

3️⃣ MyBatis 中的 Dynamic SQL(常见面试点)

XML 方式

<select id="queryUser" parameterType="map">
  SELECT * FROM user
  <where>
    <if test="name != null">
      AND name = #{name}
    </if>
    <if test="age != null">
      AND age > #{age}
    </if>
  </where>
</select>

注解方式(@SelectProvider)

@SelectProvider(type = UserSqlBuilder.class, method = "buildQuery")
List<User> query(UserQuery q);
public class UserSqlBuilder {
    public String buildQuery(UserQuery q) {
        return new SQL() {{
            SELECT("*");
            FROM("user");
            if (q.getName() != null) WHERE("name = #{name}");
            if (q.getAge() != null) WHERE("age > #{age}");
        }}.toString();
    }
}

4️⃣ 使用 SQL 构造器(高级写法)

如:

  • MyBatis SQL 类
  • JOOQ
  • QueryDSL

示例(MyBatis SQL 类):

new SQL()
  .SELECT("*")
  .FROM("user")
  .WHERE("status = 1")
  .ORDER_BY("create_time DESC")
  .toString();

三、手写 Dynamic SQL 的关键技巧

✅ 1. 永远用 WHERE 1=1 或 <where>

避免第一个条件前多一个 AND

✅ 2. 参数一定用 ? 或 #{}

❌ 不要直接拼变量

✅ 3. IN 条件处理

if (ids != null && !ids.isEmpty()) {
    sql.append(" AND id IN (");
    sql.append(ids.stream().map(i -> "?").collect(Collectors.joining(",")));
    sql.append(")");
    params.addAll(ids);
}

✅ 4. 动态 ORDER BY 要白名单

Set<String> allow = Set.of("id", "name", "age");
if (allow.contains(sortField)) {
    sql.append(" ORDER BY ").append(sortField);
}

四、常见错误

❌ SQL 注入
❌ 字符串拼接引号错误
❌ 忘记参数顺序
❌ ORDER BY 直接拼用户输入
❌ 动态 SQL 太复杂,难以维护


五、什么时候该手写 Dynamic SQL?

✅ 报表查询
✅ 多条件筛选
✅ 复杂业务 SQL
❌ 简单 CRUD(用 ORM 更好)


如果你愿意,可以告诉我:

  • 用的语言(Java / Python / Go)
  • 是否用 MyBatis / JPA
  • 具体业务场景(查询 / 更新 / 报表)

我可以直接帮你写一个完整可用的 Dynamic SQL 示例。

向AI问一下细节

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

AI
助
手