2010-01-10 272 views
24

我期待实现一种'活动日志'表,其中用户所做的动作存储在sqlite表中,然后呈现给用户,以便他们可以看到他们的最新活动完成了。然而,自然,我不觉得有必要保留每一个历史记录,所以我想知道是否有一种方法来配置表格,以便在达到最大设置限制后开始修剪较旧的行。限制sqlite表的最大行数

例如,如果限制为100,并且表格中当前有多少行,那么当插入另一个动作时,最旧的行会自动删除,因此总是最多有100行。有没有办法配置sqlite表来做到这一点?或者我会不得不运行一个cron工作?

说明性编辑:在任何时候,我想显示表格的最后100个(例如)动作/事件(行)。

回答

18

另一种解决方案是预先创建100行,而不是INSERT使用UPDATE来更新最早的行。
假设表中有一个datetime字段,查询

UPDATE ... 
WHERE datetime = (SELECT min(datetime) FROM logtable) 

可以做的工作。

编辑:显示最后100

SELECT * FROM logtable 
ORDER BY datetime DESC 
LIMIT 100 

更新:这里是通过使用连接操作来创建130 “虚拟” 行的方式:

CREATE TABLE logtable (time TIMESTAMP, msg TEXT); 
INSERT INTO logtable DEFAULT VALUES; 
INSERT INTO logtable DEFAULT VALUES; 
-- insert 2^7 = 128 rows 
INSERT INTO logtable SELECT NULL, NULL FROM logtable, logtable, logtable, 
    logtable, logtable, logtable, logtable; 
UPDATE logtable SET time = DATETIME('now'); 
+0

我想我错过了一些东西,但不会总是只更新最后一行?我想我在原来的文章中忘记提到了,但我想举例说明最后的5个动作/事件,不管他们多大年纪,而不仅仅是最后一个。不过谢谢。 – 2010-01-10 03:39:27

+2

@Blaenk:假设你的更新将datetime字段设置为它触及的每一​​行的当前时间,这应该按照时间顺序循环行。 – 2010-01-10 03:47:48

+0

Oohhh,然后还更新日期时间字段当然,这会使它成为最新的一行,对吗?我懂了。嗯,这很有趣。是否有预先创建一定数量的“虚拟”行的简单方法? – 2010-01-10 04:01:35

2

您可以创建一个在INSERT上触发的trigger,但是更好的方法来解决这个问题,可能只是定期运行(例如每周一次)并从表中删除记录。

+0

哦,好吧,这就是我想(克朗),但我想确保没有内置机制的这种情况。 – 2010-01-10 01:55:05

+1

如果你熟悉触发器,你会提供一个可用于这种情况的示例吗?也就是说,如果他们不太复杂,如果他们是,不要担心。 – 2010-01-10 04:02:27

3

有有几种方法可以将约束为一个表格到100行。 (为了简洁起见,下面的代码中有5行。)在SQLite 3.7.9版本中测试。

所有这些代码都依赖于SQLite处理数据类型声明的一种怪癖。 (无论如何,这对我来说似乎很古怪。)SQLite允许你像3.14159和'wibble'一样插入一个无用的数据到一个裸整数列中。但它可以让你只将整数插入到一个名为integer primary keyinteger primary key autoincrement的列中。

外键约束

使用外键约束有效身份证件号码表,以保证ID号是你想要的范围。即使在自动增量列上,外键约束也可以工作。

pragma foreign_keys=on; 
create table row_numbers (n integer primary key); 

insert into row_numbers values (1); 
insert into row_numbers values (2); 
insert into row_numbers values (3); 
insert into row_numbers values (4); 
insert into row_numbers values (5); 

create table test_row_numbers (
    row_id integer primary key autoincrement, 
    other_columns varchar(35) not null, 
    foreign key (row_id) references row_numbers (n) 
); 

insert into test_row_numbers (other_columns) values ('s'); 
insert into test_row_numbers (other_columns) values ('s'); 
insert into test_row_numbers (other_columns) values ('s'); 
insert into test_row_numbers (other_columns) values ('s'); 
insert into test_row_numbers (other_columns) values ('s'); 

第六次插入失败,并显示“错误:外键约束失败”。

我不要认为使用自动增量是完全安全的。在其他平台上,回滚会在顺序上留下空隙。如果您不使用自动增量,则可以通过从“row_numbers”中选取id号来安全地插入行。

insert into test_row_numbers values 
(
    (select min(n) 
    from row_numbers 
    where n not in 
    (select row_id from test_row_numbers)), 
    's' 
); 

CHECK()约束

下面的主键约束保证ID号将是整数。 CHECK()约束保证整数将在正确的范围内。您的应用程序可能仍然需要处理回滚造成的差距。

create table test_row_numbers (
    row_id integer primary key autoincrement, 
    other_columns varchar(35) not null, 
    check (row_id between 1 and 5) 
);