偏好 SQLite 中的严格表
严格表 vs 默认行为
- 许多人认为
STRICT表应该成为默认设置,甚至在未来版本中成为唯一模式。 - 也有人反驳说,
STRICT只是众多偏好之一;SQLite 目前的行为是有意为之,并且适合它所处的细分场景。 - 还有人建议使用全局 pragma,或“默认集”/版本化默认值(例如“使用 2026.1 默认值”),以在不破坏旧代码的情况下启用严格性和其他更安全的选项。
SQLite 的类型哲学与历史
- SQLite 起步于一个“所有东西都是字符串/数字”的世界(Tcl、dbm 风格存储),其动态类型特性基本延续到了 SQLite 3。
- 项目文档明确为灵活类型辩护;线程中的批评者往往觉得这些理由站不住脚,或者像是事后补充的说法。
- 支持者强调 SQLite 是“对
fopen的竞争”,而不是 Oracle/Postgres;在你能在应用代码中证明正确性的情况下,他们认为严格的运行时检查只是可选开销。
实际问题:类型、日期、布尔值
- 常见抱怨包括:
- 默认不强制列类型。
- 没有原生
DATE/TIMESTAMP/BOOL类型,在STRICT模式下尤其别扭。 - 一些意外情况,例如整数列接受任意文本,以及字符串中的 NUL 字节会影响
length()等函数。
- 变通办法:将日期存为文本或 Unix 时间戳;将布尔值存为整数或位字段;通过
CHECK约束进行强制。
向后兼容性与默认值
- SQLite 极少更改默认值(例如外键默认关闭、WAL 默认关闭),以避免破坏现有软件。
- 有人认为这是负责任的做法;也有人认为这迫使新用户一个个学习并关闭这些“脚枪”。
- 关于“令人意外的类型接受”是否比升级时破坏旧代码更糟,存在争论。
迁移、工具与模式
- SQLite 中的模式迁移被认为比较笨重;第三方工具和模式试图简化这一点。
STRICT表不能通过简单的ALTER切换;通常做法是重建并复制,不过有些工具会自动化这一过程。- 对于严格模式是否能改善更高层语言集成(例如 Rust/Go ORM)或是否会让类型映射更复杂,意见分歧很大。