2008-10-01 54 views
1

我们有一个数据库,用于存储嵌入式设备的测试结果。有一张表格,列出了不同类型的失败(细节不相关),以及主键'keynum'和'NUM_FAILURES'列,列中列出了失败的次数。我们存储通行证和故障,所以通行证在'NUM_FAILURES'中有'0'。用于删除旧结果的SQL触发器

为了防止数据库无限制地增长,我们希望保留最近的1000个结果,以及最后50个超出1000的故障中的任何一个。所以,最糟糕的情况是,表中可能有1050个条目它。我试图找到最有效的SQL插入触发器来删除额外的条目。我会给我迄今为止的答案,但我期待着看看是否有人能够提出更好的东西,因为SQL不是我经常做的事情。

我们在非Windows平台上使用SQLITE3,如果它是相关的。

编辑:为了澄清,我有问题的部分是DELETE,特别是与最近50次失败有关的部分。

回答

1

你想删除这些条目的原因是为了保持数据库的增长过大,而不是保持它在某种特殊的状态。为此,我真的不会使用触发器,而是设置一个作业,以在某个时间间隔运行清理表格。

+0

通常这是正确的,但问题指定了一个嵌入式设备,所以我们不能认为有任何机制可以做到这一点,或者如果它是可取的。 – Cruachan 2008-10-01 12:28:38

+0

Cruachan关于该平台。而且,触发器本身并不是真正的问题。这是我遇到麻烦的DELETE部分。即使我将它作为单独线程的一部分,情况也是如此。 – mbyrne215 2008-10-01 12:41:28

0

到目前为止,我已经结束了使用视图结合触发器,但我不知道它会因其他原因工作。

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; 
0

我想你可能会使用错误的数据结构。相反,我会创建两个表,并预先填充1000个行(成功),另一个填充50个(失败)。在每个上放一个主要ID。当你记录一个结果而不是插入一个新行时,找到上一次输入的时间戳记录的ID + 1值(如果表中的> max(id),则循环回0),并用新值更新它。

这具有预分配存储的优点,不需要触发器和内部一致的逻辑。您还可以通过预先填充更多记录来调整日志的大小,而不必更改程序逻辑。

您可以在此上使用几种变体,但使用闭环结构而不是打开列表的想法似乎更接近地匹配问题域。

+0

有几个原因为什么这不适合我。对于初学者,我们在系统中始终没有准确的时间和日期标记。另外,我需要失败并以正确的关系传递给对方。 – mbyrne215 2008-10-01 12:46:01

0

如何:

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

如果性能是一个问题,它可能是最好删除定期,而不是在每次插入。