SQL查表结构差异需依数据库调用information_schema(MySQL)或pg_columns(PG),但NOT IN易误判顺序差异;pt-table-sync可生成ALTER语句,sqlglot支持AST级DDL比对,JSON Schema比对更适API契约场景。
用 SQL 查两张表的字段差异(MySQL / PostgreSQL)
直接查字段名、类型、是否为空这些基础结构差异,不用导出再比对。核心是查系统表或信息模式(information_schema),但不同数据库写法有区别。
MySQL 示例(对比 table_a 和 table_b):
SELECT column_name, data_type, is_nullable, column_default FROM information_schema.columns WHERE table_name = 'table_a' AND table_schema = 'your_db' AND column_name NOT IN ( SELECT column_name FROM information_schema.columns WHERE table_name = 'table_b' AND table_schema = 'your_db' );
PostgreSQL 要换用 pg_attribute + pg_class,更绕一点;建议用 SELECT * FROM pg_columns WHERE table_name = 'xxx' 先看齐字段,再用 EXCEPT 做集合差。
- 别漏掉
table_schema条件,多库同名表容易串库 -
column_default在 MySQL 里可能带括号(如CURRENT_TIMESTAMP),而 PostgreSQL 返回的是表达式字符串,格式不一致,不能直接等值比对 - 某些字段顺序不同但结构相同,
NOT IN会误报,得加全字段组合判断
用 pt-table-sync 快速定位并生成 DDL 差异(MySQL 生产环境)
开发说“结构一样”,运维一跑发现主从字段顺序错位、默认值写法不一致、甚至多了个 COMMENT ——这种细节人工核对极容易漏。pt-table-sync 不只同步数据,加 --dry-run 和 --print 就能输出结构差异对应的 ALTER TABLE 语句。
- 必须确保两个表在同一个实例,或配置好
--databases和--tables,跨实例它不处理结构比对 - 它默认忽略
COMMENT和字段顺序,要加--ignore-columns=comment或显式打开顺序检查(用--alter-foreign-keys-method=none配合手动 review) - 输出的
ALTER不一定可直接执行:比如把INT改成BIGINT会提示需要ALGORITHM=INPLACE,但老版本 MySQL 不支持
用 Python 的 sqlglot 解析建表语句做语法级比对
当只有建表 SQL 文本(比如 Git 里存的 DDL 文件),没有实际数据库连接权限时,靠字符串比对或正则极不可靠——NULL DEFAULT NULL 和 DEFAULT NULL 语义相同,但文本不同;datetime 和 timestamp 在某些版本也自动转换。
sqlglot 能把 SQL 解析成 AST,再标准化后比对节点:
import sqlglot
a = sqlglot.parse_one("CREATE TABLE t (id INT)")
b = sqlglot.parse_one("CREATE TABLE t (id INTEGER)")
print(a == b) # True,因为都转成 INT 类型节点- 它不校验数据库实际行为(比如 MySQL 的
TINYINT(1)当布尔用,sqlglot只认类型,不认业务含义) - 对自定义函数、存储过程、分区语法支持有限,遇到就抛
ParseError,得提前过滤掉非 CREATE TABLE 语句 - 输出差异只能到 AST 节点级别,没法直接告诉你“第 3 行少了个 NOT NULL”,得自己递归 diff
同步配置时,jsonschema 比 diff 更可靠(尤其用于 API 或配置中心)
表结构只是结果,背后常对应一份 JSON Schema 描述(比如微服务间约定的 DTO 结构)。这时候比对原始 DDL 不如比对 schema 定义——字段增删、类型变更、必填项变化都能映射为 JSON Schema 的 required、type、properties 差异。
- 别直接用
json.dumps()后比字符串,键顺序不同就判为不同;要用json.dumps(..., sort_keys=True) -
anyOf/oneOf这类联合类型,节点等价性判断复杂,建议用jsonschema库配合fastjsonschema做运行时兼容性验证,而非静态 diff - 很多团队把 schema 存在 ZooKeeper 或 Nacos,路径层级深,
GET /v2/schema/user返回的可能是嵌套引用($ref),得先做resolve再比
结构比对真正的麻烦点不在工具选型,而在“什么算一致”——是字段名+类型严格相等?还是允许别名、隐式转换、注释差异?这些边界得和上下游团队提前对齐,否则自动化脚本跑出 200 行差异,最后发现全是预期之内的“伪差异”。

















