2010-01-10 273 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) 
);