SQLite:如何根据时间戳限制行数?

3

我成功地使用以下的 BEFORE INSERT 触发器来限制存储在 SQLite 数据库表 locations 中的行数。该数据库表在 Android 应用中充当缓存。

CREATE TRIGGER 'trigger_locations_insert'
BEFORE INSERT ON 'locations'
WHEN ( SELECT count(*) FROM  'locations' ) > '100'
  BEGIN
    DELETE FROM 'locations' WHERE '_id' NOT IN
    (
      SELECT '_id' FROM 'locations' ORDER BY 'modified_at' DESC LIMIT '100' 
    );
  END

同时,我添加了第二个触发器,允许我插入或更新行 - 有关该主题的讨论可以在另一个帖子中找到。第二个触发器需要一个视图,每个插入都会在其上执行。

CREATE VIEW 'locations_view' AS SELECT * FROM 'locations';

由于INSERT不再在TABLE locations上执行,而是在VIEW locations_view上执行,因此上面的触发器不再起作用。如果我在VIEW上应用触发器,则会抛出以下错误消息。

Failure 1 (cannot create BEFORE trigger on view: main.locations_view)

问题:

我应该如何更改上面的触发器以观察视图上的每个INSERT - 或者您是否建议另一种方法来限制行数?我更喜欢在数据库中处理这种操作,而不是在客户端运行前端代码。


性能问题:

尽管限制器(上述触发器)通常工作 - 它的性能却不太理想!实际上,数据库操作非常缓慢,会导致ANR错误。据我所见,原因是每次发生INSERT都会调用限制器。为了优化设置,批量INSERT应该被包装到一个事务中,并且限制器应该紧随其后执行。这是可能的吗?如果您愿意提供帮助,请在原问题中放置有关批量INSERT的优化评论。欢迎在此处提出有关限制器的评论。


你可以只使用代码来完成这个任务,而不是使用触发器。 - max4ever
1个回答

1
这种触发器应该能与另一个触发器很好地配合使用。问题似乎是SQL不必要地引用了_id字段。它选择每一行的字符串"_id",然后将其与同样的字符串进行比较。
DELETE和子SELECT中删除'_id'周围的引号应该可以解决问题。

谢谢。虽然出现了奇怪的错误消息,但它现在总体上能够工作了,但性能并不理想。我会将我的担忧添加到问题中。 - JJD
更新答案:我刚刚发现问题实际上是引号限制,例如 '100'。带引号的 '_id' 不是问题所在。不过,你指出了正确的方向。 - JJD
啊,有趣。知道了! - blazeroni

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接