用于删除旧结果的SQL触发器
我们有一个数据库,用于存储嵌入式设备的测试结果。有一个表,其中列用于不同类型的故障(详细信息不相关),还有一个主键“keynum”和一个列出故障数的“NUM_failures”列。我们存储过程和失败,因此过程的“NUM_failures”中有一个“0” 为了防止数据库无限制地增长,我们希望保留最后1000个结果,加上最后50个超出1000个的失败。所以,在最坏的情况下,表中可能有1050个条目。我试图找到最有效的SQL插入触发器来删除额外的条目。我会给出我目前为止的答案,但我想看看是否有人能想出更好的方法,因为SQL不是我经常做的事情 如果相关的话,我们在非Windows平台上使用SQLITE3用于删除旧结果的SQL触发器,sql,sqlite,Sql,Sqlite,我们有一个数据库,用于存储嵌入式设备的测试结果。有一个表,其中列用于不同类型的故障(详细信息不相关),还有一个主键“keynum”和一个列出故障数的“NUM_failures”列。我们存储过程和失败,因此过程的“NUM_failures”中有一个“0” 为了防止数据库无限制地增长,我们希望保留最后1000个结果,加上最后50个超出1000个的失败。所以,在最坏的情况下,表中可能有1050个条目。我试图找到最有效的SQL插入触发器来删除额外的条目。我会给出我目前为止的答案,但我想看看是否有人能想出
编辑:为了澄清,我遇到问题的部分是删除,特别是与最近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;
到目前为止,我已经使用了一个结合了触发器的视图,但我不确定它是否会因为其他原因而起作用
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值(在表中循环回0 if>max(ID)),并使用新值更新它 这样做的优点是预先分配存储空间,不需要触发器,并且内部逻辑一致。您还可以非常简单地通过预先填充更多记录来调整日志的大小,而无需更改程序逻辑
您可以在这方面使用多种变体,但使用闭环结构而不是开放列表的想法似乎更符合问题域。我认为您可能使用了错误的数据结构。相反,我将创建两个表,并预先填充其中一个1000行(成功),另一个50行(失败)。在每个服务器上放置一个主ID。当您记录一个结果而不是插入新行时,请为输入的最后一个时间戳记录查找ID+1值(在表中循环回0 if>max(ID)),并使用新值更新它 这样做的优点是预先分配存储空间,不需要触发器,并且内部逻辑一致。您还可以非常简单地通过预先填充更多记录来调整日志的大小,而无需更改程序逻辑 您可以在这方面使用多种变体,但使用闭环结构而不是开放列表的想法似乎更符合问题域。这是怎么回事:
DELETE
FROM table
WHERE ( id > ( SELECT max(id) - 1000 FROM table )
AND num_failures = 0
)
OR id > ( SELECT max(id) - 1050 FROM table )
如果性能是一个问题,那么最好定期删除,而不是每次插入 这个怎么样:
DELETE
FROM table
WHERE ( id > ( SELECT max(id) - 1000 FROM table )
AND num_failures = 0
)
OR id > ( SELECT max(id) - 1050 FROM table )
如果性能是一个问题,那么最好定期删除,而不是每次插入 一般来说,这是正确的,但问题是指定了一个嵌入式设备,因此我们不能假设有任何机制可以实现这一点,或者假设它是可取的。Cruachan对该平台的看法是正确的。而且,触发器本身并不是真正的问题;这是它的删除部分,我有麻烦。即使我是作为一个单独线程的一部分做的,这也是一样的。一般来说,这是正确的,但问题指定了一个嵌入式设备,所以我们不能假设有任何机制可以做到这一点,或者如果有,这将是可取的。Cruachan对这个平台的看法是正确的。而且,触发器本身并不是真正的问题;这是它的删除部分,我有麻烦。即使我是作为一个单独线程的一部分来做的,这也是一样的。这对我来说不起作用有几个原因。首先,我们并没有在任何时候都在系统中有一个准确的时间和日期戳。此外,我需要失败和失败之间保持正确的关系。这对我来说不起作用有几个原因。首先,我们并没有在任何时候都在系统中有一个准确的时间和日期戳。此外,我需要失败和通过之间的正确关系。这并不是我想要的,因为如果1000次失败中有50次失败,你不需要保持更多的失败。然而,标准可能根本不需要那么复杂。这并不是我想要的,因为如果你在1000次失败中有50次失败,你不需要让更多的失败过去。然而,标准可能根本不需要那么复杂。