RoomDB按指定年月查询事件SQLite语句返回0结果问题求助
问题原因及解决方案
1. 初始不加单引号返回空的原因
strftime 函数返回值为字符串类型,你直接和数字 11、2021 做等值比较时,SQLite的隐式类型转换会导致匹配失败,加单引号后转成字符串与字符串的比较,逻辑正确所以能查到结果。
2. 替换为参数后返回空的原因
你传入的:newMonth、:newYear大概率是整数类型,又回到了「字符串 vs 整数」的类型不匹配问题,导致等值比较失败。
修复方案
方案一:统一比较类型
要么把参数转成字符串传入,要么在SQL里把strftime的返回值转成整数再比较,同时建议给两组条件加括号,避免后续修改时因为AND/OR优先级问题出现逻辑错误:
SELECT * FROM events WHERE (CAST(strftime('%m',datetime(startDate/1000, 'unixepoch')) AS INTEGER) = :newMonth AND CAST(strftime('%Y',datetime(startDate/1000, 'unixepoch')) AS INTEGER) = :newYear) OR (CAST(strftime('%m',datetime(endDate/1000, 'unixepoch')) AS INTEGER) = :newMonth AND CAST(strftime('%Y',datetime(endDate/1000, 'unixepoch')) AS INTEGER) = :newYear) ORDER BY eventStart ASC
方案二(更推荐,性能更好)
直接用时间戳范围比较,不需要对存储的字段做函数运算,可以利用索引大幅提升查询速度:
首先在代码层计算两个参数值:
:startOfMonth:目标年月第一天0点的毫秒级时间戳,比如2021年11月对应1635724800000:startOfNextMonth:目标年月下一个月第一天0点的毫秒级时间戳,比如2021年12月对应1638316800000
如果你的需求是仅查询开始/结束时间落在目标年月的事件,SQL写为:
SELECT * FROM events WHERE (startDate >= :startOfMonth AND startDate < :startOfNextMonth) OR (endDate >= :startOfMonth AND endDate < :startOfNextMonth) ORDER BY eventStart ASC
如果你的需求是查询所有和目标年月有交集的事件(比如事件从10月持续到12月也需要命中),可以把条件改成:
SELECT * FROM events WHERE startDate < :startOfNextMonth AND endDate >= :startOfMonth ORDER BY eventStart ASC
内容的提问来源于stack exchange,提问作者madhall
相关产品推荐
相关产品推荐

