最可靠的方式是用 EXCEPT/INTERSECT 让数据库自动比对,需确保列数、类型、顺序一致,显式写字段名;宽表或含 JSON 时可用行哈希(如 md5 拼接);导出 CSV 后用 sort+comm/diff 命令行比对可复现、可存档。
用 EXCEPT 和 INTERSECT 直接比对结果集(不依赖 GUI 工具)
两条 sql 查询结果是否一致,最可靠的方式不是肉眼扫窗口,而是让数据库自己算差异。postgresql、sql server、sqlite 都支持 except(差集)和 intersect(交集),mysql 8.0+ 也已支持。
常见错误是直接拼 SELECT * FROM a EXCEPT SELECT * FROM b,但列名、顺序、空值处理稍有不一致就会漏报或误报。
- 必须确保两个查询返回的列数、类型、顺序完全一致;建议显式写出字段名,别用
* -
NULL在EXCEPT中被视为相等,但某些旧版 SQLite 行为不一致,测试前先确认SELECT NULL EXCEPT SELECT NULL是否返回空 - 若要查「a 有而 b 没有」和「b 有而 a 没有」,得写两次
EXCEPT:一次a EXCEPT b,一次b EXCEPT a - 性能上,大结果集走
EXCEPT会触发排序去重,比JOIN更重;超 10 万行建议加索引或先导出到临时表
示例:
SELECT id, name, status FROM orders WHERE created_at > '2024-01-01' EXCEPT SELECT id, name, status FROM orders_archive;
多标签/多窗口操作时,怎么避免连错库或看串结果
在 DBeaver、DataGrip 或 VS Code 的 SQL 插件里开七八个标签,很容易执行 A 标签的语句却盯着 B 标签的结果——尤其当连接名都叫 prod 或 local 时。
这不是注意力问题,是工具配置没对齐实际工作流。
- 给每个连接起带环境标识的名字,比如
prod-us-west、staging-eu,别只写production - 开启「执行前高亮当前连接」类功能(DBeaver 叫
Show connection name in editor tab;DataGrip 在Settings → Database → General → Show database name in SQL Editor tabs) - 在每条 SQL 开头加注释说明目标库:
-- [prod] 查用户余额异常,既提醒自己,也方便同事接手 - 禁用「自动提交」模式,防止 Ctrl+Enter 执行了上一个标签里的未保存修改
用 md5() 或 sha256() 做整行哈希比对(适合宽表或含 JSON 字段)
当两表结构相同但字段太多,或含 JSON、TEXT 这类不可直接比较的类型时,EXCEPT 会失败或极慢。这时把整行转成哈希再比,更稳。
注意不是所有数据库都内置行级哈希函数,得组合字段手动拼。
- PostgreSQL 可用
md5(CAST(t AS text)),但CAST(... AS text)对含NULL的行不稳定,推荐显式拼接:md5(id::text || '|' || coalesce(name, '') || '|' || status) - MySQL 要用
CONCAT_WS()处理NULL:md5(concat_ws('|', id, name, status)) - 哈希只是辅助手段,不能替代语义校验;比如金额 100.00 和 100,字符串拼接后哈希一样,但业务上可能不同
- 哈希列别忘了加索引,否则
JOIN比对时全表扫描
示例(PostgreSQL):
SELECT md5(id::text || '|' || coalesce(name, '') || '|' || status) AS row_hash FROM users;
导出 CSV 后用 diff 或 comm 命令行比对(脱离 GUI,可复现)
当需要留痕、自动化或跨团队核对时,图形界面多窗口根本不可靠。导出为规范 CSV,再用系统命令比,结果可存档、可脚本化。
关键不是“怎么导”,而是“导得能不能比”。
- 导出时强制指定字段顺序、统一时间格式(如
YYYY-MM-DD HH:MM:SS)、禁用千分位和货币符号 - 用
sort -t, -k1,1 -k2,2 file1.csv > s1.csv排序后再比,否则diff会把顺序不同当成内容不同 -
comm -3 <(sort a.csv) <(sort b.csv)能直接输出仅在 a 或仅在 b 的行(-3表示不显示共同行) - Windows 用户可用
fc,但默认不忽略空格和大小写,建议先用 PowerShell 导出并清理:Export-Csv -NoTypeInformation -Encoding UTF8
真正容易被忽略的是字段分隔符本身——如果数据里有逗号,CSV 就会错位。psql 导出请用 \copy (SELECT ...) TO 'x.csv' WITH (FORMAT csv, HEADER true, DELIMITER E'\t') 改用制表符,diff 更干净。










