各位测试小伙伴们,今天想和大家聊聊一个”老生常谈”但又特别重要的话题——SQL。
可能有同学会想:我是一个功能测试工程师,又不写代码,每天点点点就够了,学什么SQL啊?
别急,让我先给你讲个故事
一个真实的”事故”
去年我们团队有个小伙伴,负责一个订单模块的验收测试。测试环境上线后,一切看起来很正常,直到有一天——
运营突然发现:有1000多个订单的状态显示”已支付”,但实际上用户根本没付款!
查了一整天,最后发现是开发在改代码的时候,不小心把支付状态字段的默认值从”未支付”改成了”已支付”。
如果这位测试小伙伴会SQL,只要在提测前跑一条查询:
SELECT status, COUNT(*) FROM orders GROUP BY status;
就能立刻发现数据分布异常,及时拦截这个问题。
所以啊,SQL不是程序员的专利,而是测试工程师的”透视眼”。它能帮我们:
- 快速了解数据库结构
- 验证数据的正确性
- 构造各种测试数据
- 定位问题根因
今天,我就把自己日常工作中最常用的5个SQL技巧整理出来,全部是实战干货,建议收藏!
一、information_schema:摸清数据库”家底”
拿到一个新项目,面对几十上百张表,完全不知道从哪下手?
这时候就要用到information_schema这个”数据库地图”了。它存储了所有表的元数据,相当于数据库的”户口本”。
场景:接手新项目,想快速了解表结构
想看看某个数据库里有哪些表?表里有哪些字段?字段类型是什么?
-- 查看所有表
SELECT table_name, table_comment
FROM information_schema.tables
WHERE table_schema = 'your_database_name';
-- 查看某个表的所有字段
SELECT column_name, data_type, column_comment, column_key
FROM information_schema.columns
WHERE table_schema = 'your_database_name'
AND table_name = 'orders'
ORDER BY ordinal_position;
💡 小技巧:如果你用的是MySQL Workbench或Navicat,可以直接右键表→”逆向工程到模型”,自动生成ER图,一目了然!
延伸思考
除了查表结构,information_schema还能帮我们:
- 查外键关系:了解表与表之间的关联
- 查索引:了解查询性能优化
- 查字符集:避免中文乱码问题
这对我们理解业务逻辑、编写测试用例非常有帮助。
二、聚合函数:数据一致性的”照妖镜”
测试过程中,你是否遇到过这样的困惑:功能明明没问题,但总感觉数据”怪怪的”?
这时候,聚合函数就是最好的验证工具。
场景:验证订单数据一致性
比如要验证一个电商订单系统的数据一致性,我们可以:
-- 1. 检查订单状态分布
SELECT status, COUNT(*) as count
FROM orders
GROUP BY status;
-- 2. 检查订单金额是否异常(负数或为0)
SELECT * FROM orders
WHERE total_amount <= 0 OR total_amount > 1000000;
-- 3. 检查订单时间逻辑(创建时间晚于支付时间?)
SELECT order_id, created_at, paid_at
FROM orders
WHERE paid_at < created_at;
-- 4. 检查关联数据一致性(订单有明细,金额要对得上)
SELECT o.order_id, o.total_amount,
SUM(oi.price * oi.quantity) as detail_total
FROM orders o
LEFT JOIN order_items oi ON o.order_id = oi.order_id
GROUP BY o.order_id, o.total_amount
HAVING o.total_amount != detail_total
LIMIT 10;
⚠️ 重点提示:第4条SQL非常重要!我在工作中遇到过多次”订单金额和明细对不上”的问题,靠的就是这条查询发现的。
延伸思考
常用的聚合函数组合:
- COUNT + GROUP BY:统计各类数据分布
- SUM + HAVING:找出异常汇总值
- AVG + WHERE:检测极端值
- MAX/MIN:检查时间戳、ID等边界值
学会这几招,数据异常基本无处遁形。
三、INSERT/UPDATE:造数据的”魔法棒”
测试过程中,最头疼的是什么?没有测试数据!
等开发造数据?太慢。
自己手动填?太累。
学会SQL造数据,让你5分钟搞定原来半天的活儿。
场景:构造各种”极端”测试数据
-- 1. 复制现有数据(快速造一批类似数据)
INSERT INTO orders (user_id, total_amount, status, created_at)
SELECT user_id, total_amount, 'pending', DATE_ADD(created_at, INTERVAL 1 DAY)
FROM orders WHERE status = 'paid' LIMIT 100;
-- 2. 批量更新状态
UPDATE orders SET status = 'cancelled'
WHERE created_at < DATE_SUB(NOW(), INTERVAL 1 YEAR);
-- 3. 随机造一批测试用户
INSERT INTO users (username, email, phone, created_at)
SELECT
CONCAT('test_user_', n) as username,
CONCAT('test_user_', n, '@test.com') as email,
CONCAT('138', LPAD(n, 8, '0')) as phone,
NOW() as created_at
FROM (SELECT @row := @row + 1 as n FROM
(SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) t1,
(SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) t2,
(SELECT @row:=0) t3 LIMIT 1000) numbers;
🔧 实战技巧:第3条SQL看起来复杂,其实就是利用MySQL的变量机制生成1-1000的序号,然后拼接成测试数据。核心是SELECT配合CONCAT,可以造出任何你想要的数据格式。
延伸思考
造数据的进阶用法:
- 跨表复制:从A表复制到B表(结构相似时)
- 时间偏移:用DATE_ADD函数批量修改时间
- 状态机测试:手动把状态改成异常值,测试系统容错能力
⚠️ 提醒:生产环境切勿随意执行UPDATE和DELETE!建议先用SELECT确认影响范围,或者开启事务先ROLLBACK验证。
四、数据比对:找出差异的”神器”
测试过程中,你有没有遇到过这种场景:
“开发说这个功能没问题啊,为什么测试环境显示不对?”
“这个数据明明应该是A,为什么显示是B?”
这时候,我们需要数据比对来”对账”。
场景:比对前后台数据差异
-- 1. 找出订单在A表有但B表没有的
SELECT order_id FROM orders_A
WHERE order_id NOT IN (SELECT order_id FROM orders_B);
-- 2. 找出同一订单在两个表的数据差异
SELECT o1.order_id, o1.status as status_A, o2.status as status_B
FROM orders_A o1
JOIN orders_B o2 ON o1.order_id = o2.order_id
WHERE o1.status != o2.status;
-- 3. 统计差异数量
SELECT
'A表有B表无' as type, COUNT(*) as cnt FROM orders_A
WHERE order_id NOT IN (SELECT order_id FROM orders_B)
UNION ALL
SELECT 'B表有A表无' as type, COUNT(*) as cnt FROM orders_B
WHERE order_id NOT IN (SELECT order_id FROM orders_A);
延伸思考
数据比对的其他应用场景:
- 接口返回vs数据库:验证API返回数据是否和数据库一致
- 同步前后对比:数据同步后验证一致性
- 版本升级对比:升级前后数据是否丢失
有个小工具推荐:Beyond Compare,可以可视化比对两个表的数据,非常适合复杂场景。
五、高效查询:处理大量数据的”快车道”
有时候,你需要查几十万甚至上百万条数据。
如果直接SELECT * FROM orders,会发生什么?
轻则卡死,重则数据库崩溃。
所以,处理大数据量必须有”优雅”的姿势。
场景:分页查询和导出大量数据
-- 1. 分页查询(OFFSET方式,简单但有性能问题)
SELECT * FROM orders
ORDER BY created_at DESC
LIMIT 100 OFFSET 10000;
-- 2. 基于ID的分页(性能更好,推荐!)
SELECT * FROM orders
WHERE id > 10000 -- 上次查询的 最大ID
ORDER BY id
LIMIT 100;
-- 3. 分批导出到文件(MySQL命令行)
SELECT * FROM orders
INTO OUTFILE '/tmp/orders_export.csv'
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n';
-- 4. 大数据量统计(用EXPLAIN分析)
EXPLAIN SELECT status, COUNT(*) FROM orders GROUP BY status;
🚀 性能优化TIP:第2种分页方式叫”游标分页”或”ID分页”,比OFFSET性能好10倍以上!因为OFFSET越大,MySQL需要扫描跳过的行数越多。
延伸思考
处理大数据量的其他建议:
- 避免SELECT \*:只查需要的字段
- 利用索引:WHERE条件尽量走索引
- 分批处理:用LIMIT分批,避免一次性加载
- 导出工具:Navicat、DataGrip都有批量导出功能,比命令行更友好
写在最后
好啦,今天的SQL技巧分享就到这里。
回顾一下我们聊到的5个技能:
- information_schema:快速了解数据库结构
- 聚合函数:验证数据一致性
- INSERT/UPDATE:快速构造测试数据
- 数据比对:找出差异,对账必备
- 高效查询:分页和导出大数据
这些技巧不需要你背下来,而是要在实践中理解思路、举一反三。
我的建议是:建一个自己的”SQL小本本”,把工作中常用的查询保存下来,下次遇到类似场景直接改改就能用。
记住一句话:SQL不是魔法,但它能让测试工作更有”底气”。
当你学会用SQL验证数据、用SQL构造场景、用SQL定位问题,你会发现——测试的世界,比你想象的要宽广得多。