SQL触发器,用于删除旧结果

时间:2020-03-06 14:58:23  来源:igfitidea点击:

我们有一个数据库,用于存储嵌入式设备的测试结果。有一张表,其中包含用于不同类型故障的列(细节无关),以及主键" keynum"和列出故障数量的" NUM_FAILURES"列。我们存储通行证和失败通行证,因此通行证在" NUM_FAILURES"中具有" 0"。

为了使数据库不受限制地增长,我们希望保留最后1000个结果,以及最后1000个失败之外的50个失败中的任何一个。因此,在最坏的情况下,该表中可能包含1050个条目。我试图找到最有效的SQL插入触发器来删除多余的条目。我将给出到目前为止的答案,但是我想看看是否有人能提出更好的建议,因为SQL并不是我经常做的事情。

如果相关的话,我们在非Windows平台上使用SQLITE3.

编辑:澄清一下,我遇到问题的部分是DELETE,尤其是与最近50次失败有关的部分。

解决方案

我们要删除这些条目的原因是要使数据库保持太大,而不要使其处于某些特殊状态。为此,我实际上不会使用触发器,而是设置一个作业以一定间隔运行以清理表。

到目前为止,我最终将视图与触发器结合使用,但是由于其他原因,我不确定它是否可以使用。

CREATE VIEW tablename_view AS SELECT keynum FROM tablename WHERE NUM_FAILURES!='0' 
    ORDER BY keynum DESC LIMIT 50;
CREATE TRIGGER tablename_trig
  AFTER INSERT ON tablename WHEN (((SELECT COUNT(*) FROM tablename) >= 1000) or
    ((SELECT COUNT(NUM_FAILURES) FROM tablename WHERE NUM_FAILURES!='0') >= 50))
  BEGIN
     DELETE FROM tablename WHERE ((((SELECT MAX(keynum) FROM ibit) - keynum) >= 1000)
  AND 
     ((NUM_FAILURES=='0') OR ((SELECT MIN(keynum) FROM tablename_view) > keynum)));
  END;

我认为我们可能使用了错误的数据结构。取而代之的是,我将创建两个表,并预先填充一个表,其中包含1000行(成功),而另一个则包含50行(失败)。在每个标签上放置一个主要ID。当我们记录结果而不是插入新行时,找到输入的最后一个带有时间戳的记录的ID + 1值(如果表中的max(id)>,则返回0)并用新值对其进行更新。

这具有预分配存储(不需要触发器)和内部一致逻辑的优点。我们也可以非常简单地调整日志的大小,只需预填充更多记录,而不必更改程序逻辑。

我们可以在其中使用多种变体,但是使用闭环结构而不是开放列表的想法似乎可以更紧密地匹配问题域。

这个怎么样:

DELETE  
FROM  table 
WHERE ( id   > ( SELECT max(id) - 1000 FROM table ) 
        AND  num_failures   = 0 
      )
OR    id     > ( SELECT max(id) - 1050 FROM table )

如果需要考虑性能,则最好定期删除而不是每次插入都删除。