web-dev-qa-db-ja.com

sqliteテーブルの最大行数を制限する

ユーザーが行ったアクションがsqliteテーブルに保存され、ユーザーに提示されて、ユーザーが行った最新のアクティビティを確認できる、一種の「アクティビティログ」テーブルを実装しようとしています。ただし、当然、履歴をすべて保持する必要はないと思います。そのため、設定された最大制限に達したときに古い行のプルーニングを開始するようにテーブルを構成する方法があるかどうか疑問に思います。

たとえば、制限が100で、それが現在テーブルにある行数である場合、別のアクションが挿入されると、最も古い行が自動的に削除されるため、常に最大100行になります。これを行うようにsqliteテーブルを構成する方法はありますか?または、cronジョブを実行する必要がありますか?

Clarification Edit:いつでも、テーブルの最後の100(たとえば)アクション/イベント(行)を表示したいと思います。

28

別の解決策は、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'); 
20

INSERTで起動する trigger を作成することもできますが、これにアプローチするためのより良い方法は、定期的に(たとえば、週に1回)実行され、テーブルからレコードを削除するスケジュールされたジョブを作成することです。

4
Mitch Wheat

テーブルを100行に制約する方法はいくつかあります。 (簡潔にするために、以下のコードでは5行です。)SQLiteバージョン3.7.9でテスト済み。

このコードはすべて、SQLiteがデータ型宣言を処理する方法の一種の癖に依存しています。 (とにかく、私には奇妙に思えます。)SQLiteを使用すると、3.14159や「wibble」などのナンセンスを裸の整数列に挿入できます。ただし、integer primary keyまたはinteger 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');

6番目の挿入は「エラー:外部キー制約に失敗しました」で失敗します。

私は考えていません自動インクリメントを使用することは完全に安全です。他のプラットフォームでは、ロールバックによってシーケンスにギャップが残ります。自動インクリメントを使用しない場合は、「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)
);