Skip to content

前端开发者的 SQL 实战学习文档

更新: 6/28/2026 字数: 0 字 时长: 0 分钟

不讲运维、不讲调优黑魔法,只讲你对接后端、查业务库时真正用得上的那部分

作为前端,你不需要会搭主从、调缓冲池,但你大概率会遇到这些场景:自己查库核对数据、写个小后端接口、排查"为什么这条数据没显示"、给后端同学提需求时说清楚要哪些字段。这份文档就按这个目标来,从最基础的"表是什么"讲到日常最常用的查询、增删改,最后给你一份避坑清单。

一、先建立直觉:数据库里的"表"就是你熟悉的二维数组

前端眼中的数据库与表

别被"数据库"三个字吓到。用前端的语言翻译一下:

  • 一个数据库(database)≈ 一个项目的数据仓库;
  • 一张表(table)≈ 一个 Array<Object>,也就是你接口返回的那个列表;
  • 行(row)≈ 数组里的一个对象 { id: 1, name: '张三' }
  • 列(column)≈ 对象的某个字段(key),并且每列有固定类型(数字、字符串、时间等)。

你页面上渲染的表格、列表,几乎都来自某张表里的若干行。理解了这个映射,后面的 SQL 就只是"用另一种语法操作这个数组"而已。

几个高频字段类型,知道就行:

类型对应 JS说明
INT / BIGINTnumber整数,主键 id 常用
VARCHAR(n)string变长字符串,n 是最大长度
TEXTstring长文本,比如文章内容
DECIMALnumber精确小数,金额必用(别用 float)
DATETIME / TIMESTAMPstring/Date时间
TINYINT(1)boolean0/1 表示真假

坑点:金额、价格永远别用 FLOAT/DOUBLE,浮点精度会让 0.1 + 0.2 ≠ 0.3 的问题搬到数据库里。用 DECIMAL(10,2)

二、SELECT:查数据,你 80% 的时间都在干这个

SELECT 从表里取数

SELECT 就是"从表里取数据"。最基础的形态:

sql
-- 取 users 表的所有列、所有行
SELECT * FROM users;

-- 只取需要的列(推荐这么写)
SELECT id, name, email FROM users;

* 表示所有列。开发里强烈建议只写你要的列,原因后面避坑章节细说。

可以给列起别名,方便前端拿到想要的字段名:

sql
SELECT name AS userName, created_at AS createdTime FROM users;

坑点:SQL 里字符串和"等于"判断用单引号 '张三',不是双引号。= 是判断相等(不是 ==)。这两点最容易让前端栽跟头。

三、WHERE + ORDER BY + LIMIT:筛选、排序、分页三件套

WHERE 筛选 ORDER BY 排序 LIMIT 分页

这三个是做列表页的标配,几乎对应你每个"带搜索、带排序、带翻页"的接口。

WHERE:按条件筛选

sql
-- 单条件
SELECT * FROM users WHERE status = 1;

-- 多条件组合
SELECT * FROM users WHERE status = 1 AND age > 18;

-- 范围、枚举、模糊
SELECT * FROM users WHERE age BETWEEN 18 AND 30;
SELECT * FROM users WHERE id IN (1, 2, 3);
SELECT * FROM users WHERE name LIKE '张%';   -- 以"张"开头

常用运算符:= != > < >= <=AND ORINBETWEENLIKE% 匹配任意多字符,_ 匹配单字符)。

坑点 1:判断"空"不能用 = NULL,必须用 IS NULL / IS NOT NULLNULL 在 SQL 里是个特殊存在,和任何值(包括它自己)比较都不为真。 坑点 2LIKE '%关键词%'(前面带 %)会让索引失效,数据量大时很慢。做模糊搜索别滥用。

ORDER BY:排序

sql
SELECT * FROM users ORDER BY created_at DESC;   -- 时间倒序,最新在前
SELECT * FROM users ORDER BY age ASC, id DESC;  -- 多字段排序

DESC 降序,ASC 升序(默认)。

LIMIT:分页(前端最关心)

sql
-- 取前 10 条
SELECT * FROM users LIMIT 10;

-- 分页:跳过 20 条,再取 10 条(即第 3 页,每页 10 条)
SELECT * FROM users LIMIT 10 OFFSET 20;
-- MySQL 也可写成 LIMIT 20, 10  (注意:是 offset 在前)

前端分页的 pageNum / pageSize 换算公式:

OFFSET = (pageNum - 1) * pageSize
LIMIT  = pageSize

坑点LIMIT 100000, 10 这种深翻页会越翻越慢(数据库要先扫过前 10 万行)。海量数据分页一般改用"记住上一页最后一个 id,WHERE id > lastId LIMIT 10"的游标方式——这点了解即可,真遇到和后端沟通。

四、JOIN:多表关联,搞懂这个你就超过一半前端了

JOIN 多表关联

真实业务里数据是拆开存的:用户信息在 users 表,订单在 orders 表,订单里只存一个 user_id 指向用户。要把"订单 + 下单人姓名"一起查出来,就得用 JOIN 把两张表拼起来。

sql
-- 查每个订单,以及对应的用户名
SELECT 
  orders.id,
  orders.amount,
  users.name AS userName
FROM orders
INNER JOIN users ON orders.user_id = users.id;

ON 后面是"两张表靠哪个字段关联",这里是 orders.user_id = users.id

两种最常用的 JOIN,理解差异即可:

类型效果场景
INNER JOIN只返回两边都匹配上的行(交集)订单一定有用户,用这个
LEFT JOIN保留左表所有行,右表没匹配到的填 NULL查"用户及其订单(可能没订单)"用这个
sql
-- 查所有用户,哪怕他一个订单都没有
SELECT users.name, orders.id AS orderId
FROM users
LEFT JOIN orders ON users.id = orders.user_id;

坑点 1:多表查询时,两张表可能有同名列(比如都叫 id),一定要用 表名.列名 或别名区分,否则报"字段歧义"错误。 坑点 2LEFT JOIN 后如果在 WHERE 里写右表的条件(如 WHERE orders.status = 1),会把没匹配上的 NULL 行过滤掉,效果退化成 INNER JOIN。这类条件应写在 ON 里。

五、GROUP BY + 聚合函数:统计类需求的核心

GROUP BY 分组聚合统计

凡是"统计""每个××的数量/总和""排行榜"这类需求,都靠 GROUP BY + 聚合函数。

常用聚合函数:COUNT() 计数、SUM() 求和、AVG() 平均、MAX()/MIN() 最值。

sql
-- 总共有多少用户
SELECT COUNT(*) FROM users;

-- 每个状态各有多少用户(分组统计)
SELECT status, COUNT(*) AS num
FROM users
GROUP BY status;

-- 每个用户的订单总金额
SELECT user_id, SUM(amount) AS total
FROM orders
GROUP BY user_id;

如果要对"分组后的结果"再做筛选,用 HAVING(不是 WHERE):

sql
-- 找出下单总金额超过 1000 的用户
SELECT user_id, SUM(amount) AS total
FROM orders
GROUP BY user_id
HAVING total > 1000;

坑点 1WHERE 在分组过滤原始行,HAVING 在分组过滤统计结果。顺序记牢:WHERE → GROUP BY → HAVING坑点 2:用了 GROUP BY 后,SELECT 里只能出现"分组字段"和"聚合函数"。写个没分组又没聚合的普通列,有些数据库报错,有些返回不可预期的值。

六、INSERT / UPDATE / DELETE:写数据,慎之又慎

增删改 INSERT UPDATE DELETE

查询出错最多是查不到,写数据出错可能是线上事故。这三个语句务必小心。

INSERT:新增

sql
INSERT INTO users (name, email, status)
VALUES ('张三', 'zhang@test.com', 1);

-- 一次插多条
INSERT INTO users (name, email) VALUES
('李四', 'li@test.com'),
('王五', 'wang@test.com');

UPDATE:修改

sql
UPDATE users SET status = 0 WHERE id = 5;

-- 同时改多个字段
UPDATE users SET name = '张三丰', status = 1 WHERE id = 5;

DELETE:删除

sql
DELETE FROM users WHERE id = 5;

⚠️ 头号大坑(必须吃透)UPDATEDELETE 一定要带 WHEREDELETE FROM users;清空整张表UPDATE users SET status = 0; 会把所有人改掉。这是最经典、最致命的事故。

自保习惯:写更新/删除前,先用相同的 WHERE 写一条 SELECT 确认"我要操作的就是这几行",确认无误再把 SELECT * 换成 DELETEUPDATE

sql
SELECT * FROM users WHERE id = 5;   -- 先确认范围
DELETE FROM users WHERE id = 5;     -- 再执行

七、前端写 SQL 的避坑清单(重点收藏)

前端写 SQL 的注意事项

把前面散落的坑点汇总成一份可对照的清单,写 SQL 前过一遍:

安全相关(最重要)

  1. 永远用参数化查询,杜绝字符串拼接。绝不要把用户输入直接拼进 SQL,否则就是 SQL 注入漏洞。
    js
    // ❌ 危险:拼接
    db.query(`SELECT * FROM users WHERE name = '${input}'`);
    // ✅ 正确:参数化(占位符由驱动转义)
    db.query('SELECT * FROM users WHERE name = ?', [input]);
  2. 写库操作(UPDATE/DELETE)务必带 WHERE,并先用 SELECT 验证范围。

性能相关

  1. 别用 SELECT *,明确列出需要的字段——减少传输量,也避免后端加字段时把敏感信息(如密码)带给前端。
  2. 查询尽量带 LIMIT,尤其是不确定数据量时,防止一次拉回几十万行把服务和页面拖垮。
  3. 慎用前置模糊匹配 LIKE '%xx%'深翻页 LIMIT 大offset,数据量大时性能差,必要时找后端用其他方案。

正确性相关

  1. 判空用 IS NULL / IS NOT NULL,不能用 = NULL
  2. 金额用 DECIMAL,不要用浮点类型。
  3. 时间、时区注意统一,数据库存的时间和前端展示的时区可能不一致,跟后端约定好格式(一般用 UTC 时间戳传输)。
  4. WHEREHAVING 别用错:行级过滤用 WHERE,分组后过滤用 HAVING

协作习惯

  1. 生产环境的库别直接动手改,尤其是写操作,走后端接口或让有权限的同学审核。能用只读账号查就用只读账号。

结尾:你需要掌握到什么程度

对前端来说,目标不是成为 SQL 专家,而是做到这几点就够用了:能独立查库核对数据、能看懂后端写的 SQL、能写出带筛选排序分页的查询、能安全地做简单增删改、知道哪些写法有坑会被 review 打回

把本文的 SELECT + WHERE + ORDER BY + LIMIT + JOIN + GROUP BY 这条主线练熟,再把第七节的避坑清单刻进肌肉记忆,日常工作中的 SQL 需求基本都能从容应对。