Skip to content

072. SQL 构建器:新增、更新、删除与查询

学习目标

这一节开始拆通用模块的 SQL 构建器。

学完后,你应该能理解:

  • 通用模块为什么要生成 SQL;
  • 新增、更新、删除 SQL 的基本结构;
  • 占位符和参数化查询怎么保护安全;
  • 查询 SQL 为什么最复杂;
  • 去重、格式化、筛选和模糊查询如何落到 SQL。

四类 SQL 构建器

通用模块主要需要四类 SQL:

  • 新增 SQL;
  • 更新 SQL;
  • 删除 SQL;
  • 查询 SQL。

前三类相对简单。

查询最复杂。

因为查询要处理字段、关联、筛选、排序、分页、统计和去重。

新增 SQL

新增 SQL 的基本结构是:

sql
INSERT INTO table_name (field_a, field_b)
VALUES (%s, %s)

构建时要确定三件事:

  • 表名;
  • 字段名;
  • 字段值。

字段值不要直接拼进 SQL 字符串。

应该用占位符,再把真实值放进参数列表。

字段命名映射

前端传的是驼峰命名。

数据库字段是下划线命名。

所以 SQL 构建前需要字段格式化。

例如:

txt
leaderId -> leader_id

通用模块会把字段配置整理成可用结构。

这样生成 SQL 时能知道:

  • 前端字段名是什么;
  • 数据库字段名是什么;
  • SQL 里应该写哪个字段表达式。

主表字段和关联字段

有些字段来自主表。

有些字段来自关联表或子查询。

例如项目表里的负责人名称,可能来自用户表。

这种字段可以查询,但不能直接插入或更新到项目主表。

所以新增和更新时,只处理主表字段。

关联字段、统计字段要跳过。

占位符

参数化查询需要占位符。

不同语言和数据库驱动的占位符不完全一样。

有的使用:

sql
?

有的使用:

sql
%s

课程项目里使用 %s

SQL 字符串里放占位符。

真实参数单独传给数据库驱动。

更新 SQL

更新 SQL 的基本结构是:

sql
UPDATE table_name
SET field_a = %s, field_b = %s
WHERE id = %s

注意 SET 后面的多个字段用逗号分隔。

不是用 AND

参数数量要和占位符数量一致。

用于调试的 SQL 字符串和真正执行的 SQL 可能不一样。

真正执行时仍然要走参数化。

数据库类型转换

有时传入值是字符串,但数据库字段是数字。

数据库可能会尝试隐式转换。

例如把 "1" 转成整数 1

但不要依赖这种行为处理所有情况。

通用模块最好在字段类型层面提前转换和校验。

这样错误更早、更明确。

事务和脏数据

一次执行多条 SQL 时需要事务。

如果某一条失败,前面已经执行的 SQL 应该回滚。

脏数据的来源很多。

例如:

  • 手动执行 SQL 改错数据;
  • 前端页面字段没处理对;
  • 后端没有校验;
  • 并发覆盖;
  • 测试数据残留。

只要数据和业务预期不一致,就可以把它当成脏数据处理。

删除 SQL

删除通常只允许按 ID 删除。

单个 ID 可以用:

sql
WHERE id = %s

批量 ID 可以用:

sql
WHERE id IN (...)

删除条件不要开放得太自由。

否则很容易误删大范围数据。

查询 SQL 最复杂

查询构建器要处理更多场景。

例如:

  • 字段格式化;
  • 日期格式化;
  • 关联表字段;
  • 字段别名;
  • 去重查询;
  • 筛选表达式;
  • 排序;
  • 分页;
  • 子查询;
  • 聚合字段。

这也是通用模块最核心的一块。

日期格式化

数据库查出来的时间可能是日期对象。

但接口返回给前端时,通常希望是格式化后的字符串。

SQL 里可以使用数据库函数格式化日期。

例如把创建时间转成固定格式的字符串。

这样前端拿到的值更稳定。

关联字段别名

当查询多张表时,字段名可能冲突。

例如主表和用户表都有 name 字段。

这时要给字段加别名。

否则返回结果里会互相覆盖,或者数据库直接报字段歧义。

通用模块会根据表别名和字段配置生成更安全的字段名。

去重查询

有些字段适合做去重。

例如审批状态只有几种值。

可以用去重查询拿到所有出现过的状态。

这常用于前端筛选项。

比如先查出当前表里有哪些省份、哪些状态,再展示为筛选选项。

筛选查询

通用模块要支持多种筛选。

数字和日期常见筛选包括:

  • 等于;
  • 大于;
  • 小于;
  • 范围查询。

字符串常见筛选包括:

  • 精确匹配;
  • 模糊匹配;
  • 多值模糊匹配。

模糊查询通常用 LIKE

% 表示任意字符。

例如:

sql
LIKE '%abc%'

表示只要中间包含 abc 就匹配。

直接 SQL 和 ORM 的选择

不是所有写操作都必须先查再改。

如果业务允许弱一致性,直接执行更新 SQL 就可以。

例如普通后台字段被后提交的人覆盖,业务可以接受。

但如果涉及状态判断,就需要先查再决定。

例如用户激活:

  • 先查用户是否已经激活;
  • 未激活才更新;
  • 已激活就不重复处理。

所以项目里可以同时使用 ORM 和通用 SQL。

具体业务逻辑用 ORM 更清晰。

复杂查询和通用列表更适合通用 SQL 构建器。

这一节的重点

这一节开始进入通用模块核心。

你需要记住:

  • 新增、更新、删除 SQL 结构简单,但必须参数化;
  • 主表字段可以写入,关联字段和统计字段不能直接写入;
  • 查询构建器最复杂,要处理字段、关联、筛选、排序和分页;
  • 日期、别名、去重、模糊查询都要在 SQL 层设计清楚;
  • ORM 和手写 SQL 可以并存,按业务复杂度选择。

AI Agent 课程学习文档。