偏好 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)或是否会让类型映射更复杂,意见分歧很大。