查某段时间内的记录变化应使用 WHERE + 时间戳字段范围查询,如 updated_at >= '2024-05-01 00:00:00' AND updated_at < '2024-05-02 00:00:00',避免用等值匹配导致失败。

查某段时间内的记录变化,用 WHERE + 时间戳字段最直接
数据库里只要有 created_at、updated_at 这类时间戳字段,查“某段时间内新增或修改过哪些记录”就是标准 WHERE 范围查询。别绕路去连表比对快照,除非你真在做 CDC。
- 常见错误是写成
WHERE updated_at = '2024-05-01'—— 时间戳带秒级精度,等于匹配几乎必失败,得用范围:WHERE updated_at >= '2024-05-01 00:00:00' AND updated_at - MySQL 8.0+ 和 PostgreSQL 支持
TIMESTAMP字段自动更新,但 SQLite 需手动维护;如果业务逻辑没保证updated_at每次都更新,它就不可信 - 注意时区:
NOW()、CURRENT_TIMESTAMP返回的是数据库服务器本地时区时间,和应用层传入的 UTC 时间可能不一致,建议统一存 UTC,查询时也用 UTC 范围
想看两条记录之间具体哪几列变了,得靠行级对比
SQL 本身不提供“字段级差异”函数,SELECT 只能返回整行。真要定位到 status 从 'pending' 变成 'done',得靠应用层或自定义逻辑。
- 简单场景:用自连接比对相邻版本(比如按
id或version排序),再逐字段CASE WHEN old.status != new.status THEN CONCAT('status: ', old.status, '→', new.status) END - 复杂点的可以生成 JSON 补丁:
JSON_OBJECT('field', 'price', 'old', old.price, 'new', new.price),但 MySQL 5.7 不支持 JSON 函数,PostgreSQL 更稳 - 别指望
DIFF或CHANGES这种伪函数——它们不存在于标准 SQL,某些 ORM 的调试日志里可能有,但不是数据库能力
没有时间戳字段?别硬加,先确认数据来源是否可靠
有些老表压根没 created_at,有人会想 ALTER TABLE 加字段再用 DEFAULT CURRENT_TIMESTAMP 填充历史数据——这很危险。
-
ALTER TABLE ... ADD COLUMN created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP在 MySQL 中对已有行会填 NULL 或 0000-00-00(取决于 SQL mode),不是“创建时的时间” - 如果表来自同步工具(如 Debezium、Canal),它可能自带
__source_ts_ms这类元字段,比自己猜更可信 - 实在没时间戳又必须追溯,优先查 binlog(MySQL)或 wal(PostgreSQL)——但这是 DBA 级操作,开发通常没权限,也难关联到业务主键
WHERE 时间范围慢?先看索引是否覆盖了查询条件
加了 WHERE updated_at BETWEEN ... 却响应超时,大概率是缺索引,而不是 SQL 写得不对。
- 单列索引就够:对
updated_at建INDEX idx_updated_at ON table_name(updated_at),别一上来就搞联合索引 - 如果常同时查
status和时间,再考虑(updated_at, status)联合索引,但注意字段顺序:范围查询字段(updated_at)必须放前面 - PostgreSQL 的 BRIN 索引适合大表且时间戳严格递增的场景,比 B-tree 更省空间;MySQL 没 BRIN,别被名字误导










