SQLite严格表,一行即启

SQLite STRICT表防类型错乱,一行即启

SQLite 以其灵活宽松的类型系统著称——你可以在 INTEGER 列里塞进文本,也可以给 DATE 列赋个整数。这种”包容”在快速原型开发中很便利,但在生产环境中常常变成隐形炸弹。Evan Hahn 在一篇引发热议的博文中指出:SQLite 的 STRICT 表模式是这个问题的优雅解法,而你只需要在 CREATE TABLE 末尾加上一个单词。

一行改写,杜绝类型错乱

启用严格模式出奇简单:

CREATE TABLE people (name TEXT) STRICT;

仅此而已。一旦启用 STRICT,SQLite 将拒绝不符合列类型的插入和更新操作:

-- 普通表:允许任何类型
CREATE TABLE t1 (age INTEGER);
INSERT INTO t1 (age) VALUES ('garbage'); -- ✓ 通过

-- 严格表:拒绝类型不匹配
CREATE TABLE t2 (age INTEGER) STRICT;
INSERT INTO t2 (age) VALUES ('garbage'); -- ✗ 报错

STRICT 的三重保护

1. 阻止 INSERT/UPDATE 类型不匹配:最核心的保护。值得注意的是,SQLite 仍允许无损转换——字符串 ‘123’ 可以自动转为整数 123,这是合理的兼容设计。

2. 拒绝无效列类型:默认情况下你可以创建类型为 BOGUSTYPE 的列而不报错。STRICT 模式强制列类型必须为 SQLite 支持的严格类型(INT, INTEGER, REAL, TEXT, BLOB, ANY)。

3. 利于代码生成和 ORM 映射:有了 STRICT,工具可以更可靠地推断列类型,避免因”一切皆可为”导致的映射错误。

为什么不是默认行为?

答案很简单:向后兼容。SQLite 从 2000 年诞生以来一直采用灵活类型系统,突然改变默认行为会破坏无数现有应用。Hahn 的建议是:新项目一律用 STRICT,老项目逐步迁移。

社区反应

HN 评论区几乎一边倒地支持这个观点。”这真的应该是默认行为”、”我以为这已经是默认了”是最常见的两条评论。有用户分享了 ANY 类型的巧妙用法——用于审计表中按字段追踪变更。还有开发者建议将 STRICT 纳入 SQLite 的推荐实践文档。少数反对声音认为灵活类型在某些场景下(如数据导入清洗)有其价值,但大多认可 STRICT 作为默认选项的合理性。

一个单词的改动,带来的却是类型安全质的飞跃。如果你的项目使用 SQLite,今天就可以开始加 STRICT。

原文链接:Prefer strict tables in SQLite – Evan Hahn
HN 讨论:Hacker News (199 points, 89 comments)

Leave a Reply

Your email address will not be published. Required fields are marked *