28

我希望实现一种“活动日志”表,其中用户执行的操作存储在 sqlite 表中,然后呈现给用户,以便他们可以看到他们所做的最新活动。但是,自然地,我觉得没有必要保留每一位历史记录,所以我想知道是否有一种方法可以配置表以在达到最大设置限制后开始修剪旧行。

例如,如果限制为 100,这就是表中当前的行数,当插入另一个操作时,最旧的行会自动删除,因此最多始终有 100 行。有没有办法配置 sqlite 表来做到这一点?还是我必须运行一个 cron 作业?

澄清编辑:在任何给定时刻,我想显示表格的最后 100 个(例如)动作/事件(行)。

4

3 回答 3

21

另一种解决方案是预先创建 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'); 
于 2010-01-10T02:38:20.327 回答
4

您可以创建一个在 INSERT 时触发的触发器,但解决此问题的更好方法可能是简单地安排一个定期运行的计划作业(例如每周一次)并从表中删除记录。

于 2010-01-10T01:47:58.957 回答
3

有几种方法可以将表限制为 100 行。(为简洁起见,下面的代码中有 5 行。)在 SQLite 版本 3.7.9 中测试。

所有这些代码都依赖于 SQLite 处理数据类型声明的方式中的一种怪癖。(无论如何,这对我来说似乎很古怪。)SQLite 允许您将诸如 3.14159 和“wibble”之类的废话插入到一个裸整数列中。但它允许您仅将整数插入声明的列中integer primary keyinteger primary key autoincrement

FOREIGN KEY 约束

对有效 id 编号表使用外键约束,以保证 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)
);
于 2012-08-28T20:14:37.753 回答