如何在SQLite中使用Trigger为特定表设置最大项?

问题描述 投票:0回答:1

这是一个简单的问题。

背景介绍

根据时间戳字段,我在某个表中最多只能有400行,所以旧的行会被自动删除。在这里,我们假设是3行。

这个表有很多字段,但是时间戳是最重要的。

问题是

虽然我已经成功了(看 此处),由于某些原因,它让我得到了一个额外物品的最大值,所以我只是相应地调整了它。这意味着,我得到了4个项目,而不是3个。

private const val MAX_ITEMS = 3
private val TIMESTAMP_FIELD = "timestamp"


private val DELETE_FROM_CALL_LOG_TILL_TRIGGER =
        String.format(
                "CREATE TRIGGER %1\$s INSERT ON %2\$s 
                 WHEN (select count(*) from %2\$s)>%3\$s 
                 BEGIN 
                 DELETE FROM %2\$s WHERE %2\$s._id IN " +
                        "(SELECT %2\$s._id FROM %2\$s ORDER BY %2\$s.$TIMESTAMP_FIELD DESC LIMIT %3\$d, -1);
                 END;"
                , "delete_till_reached_max", TABLE_NAME, MAX_ITEMS - 1)

我试过的方法是

我试了一下。

  • 把条件改成只插入(意思是不含 WHEN (部分)
  • 变化 LIMIT %3\$d, -1LIMIT -1 OFFSET %3\$d . 还试了一个不同于"-1 "的数字(试了0,因为我认为这是额外的)。

问题

  1. 我为什么要用 MAX_ITEMS - 1 而不是仅仅 MAX_ITEMS ? 为什么它让我有4个项目而不是3个?
  2. 如果我有 WHEN 那里?是否更好?
sql sqlite android-sqlite
1个回答
1
投票
  1. 你省略了 BEFORE | AFTER 句,所以它 BEFORE 默认情况下。这意味着您正在计算行 之前 插入,而不是在它之后。
  2. 这要看情况。一开始,当表还没有达到极限时,快速计数查找可能会节省你一些时间,因为你避免了更复杂的删除。但只要表满了,你还是要删除,所以计数只是额外的工作。

这个应该可以。

private const val MAX_ITEMS = 3
private val TIMESTAMP_FIELD = "timestamp"

private val DELETE_FROM_CALL_LOG_TILL_TRIGGER =
  String.format(
    "CREATE TRIGGER %1\$s AFTER INSERT ON %2\$s 
     FOR EACH ROW
     BEGIN 
       DELETE FROM %2\$s WHERE _id =
         (SELECT _id FROM %2\$s ORDER BY %4\$s DESC LIMIT 1 OFFSET %3\$s);
     END;"
    , "delete_till_reached_max", TABLE_NAME, MAX_ITEMS, TIMESTAMP_FIELD)

一旦表中有400行,你就可以调用触发器,比如说 trg_keep_rowcount_constant 并去除 GROUP BY null HAVING COUNT(*) > %3\$s 从代码中。

演示。https:/dbfiddle.uk?rdbms=sqlite_3.27&fiddle=ea3867e20e85927a2de047908771f4f1。

© www.soinside.com 2019 - 2024. All rights reserved.