You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQLite如何实现标题与日期(仅年月日)组合唯一约束

最优实现方案

不要在业务层做校验,这类唯一性规则的最优实现是在数据库层通过唯一索引做原子校验,性能、可靠性都远高于业务层查询校验:

  • 业务层校验存在天然缺陷:一是并发场景下容易出现竞态(两个请求同时查询判断无重复,随后都插入成功,打破唯一性规则),必须配合高等级事务锁使用,并发性能差;二是批量写入、脚本直连表等绕过业务逻辑的场景会漏校验,产生脏数据;三是每次插入前多一次查询开销,数据量增长后性能损耗会持续升高。
  • SQLite原生支持表达式唯一索引,不需要修改现有表结构,一条语句即可实现规则,校验逻辑由数据库在写入时自动执行,是B树索引级别的O(logn)复杂度,百万级以上数据也无性能压力,且100%不会出现规则绕过的问题。

具体实现方式

因为你存储的是标准ISO格式日期字符串,前10位固定为YYYY-MM-DD格式的自然日部分,直接用字符串截取即可提取日期,性能比调用日期函数更高,也不会引入时区转换的意外问题。直接执行以下语句创建唯一索引即可:

CREATE UNIQUE INDEX idx_uq_title_day ON TABLE_A(TITLE, substr(DATE, 1, 10));

创建完成后,你示例中第二条同标题同日不同时间的插入语句会直接触发唯一约束冲突,被数据库拒绝,完全匹配你的规则要求。

可选适配方案

如果你担心后续存入的DATE值可能存在非标准格式,也可以用SQLite内置的date()函数提取自然日部分,兼容性更好,性能差异日常使用完全感知不到:

CREATE UNIQUE INDEX idx_uq_title_day ON TABLE_A(TITLE, date(DATE));

如果你偏好显式字段的实现方式,也可以在表中增加生成列存储日期部分,再给生成列和TITLE加联合唯一约束,效果和表达式索引完全一致:

-- 新建表场景可直接用这个结构
CREATE TABLE TABLE_A (
    ID INTEGER PRIMARY KEY AUTOINCREMENT,
    TITLE TEXT NOT NULL,
    DATE TEXT NOT NULL,
    DATE_ONLY TEXT GENERATED ALWAYS AS (substr(DATE, 1, 10)) STORED,
    UNIQUE(TITLE, DATE_ONLY)
);

额外收益

创建这个联合唯一索引后,后续你按标题+自然日查询数据时(比如统计某标题某天的记录),SQLite会直接命中这个索引,查询性能也会大幅提升,不需要额外再建普通索引。


内容的提问来源于stack exchange,提问作者user3320813

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 12:18:19