2009-12-29 5 views
10

Ich möchte eine SQL-Tabelle erstellen, die nicht mehr als n Datenzeilen enthält. Wenn eine neue Zeile eingefügt wird, möchte ich, dass die älteste Zeile entfernt wird, um Platz für die neue Zeile zu schaffen.Rollende Zeilen in der SQL-Tabelle

Gibt es eine typische Vorgehensweise in SQLite?

Sollte es mit etwas außerhalb (Dritter) Code verwalten?

Antwort

11

auf Alex' answer erweitern, und vorausgesetzt, Sie haben eine Inkrementierung, sich nicht wiederholende Serien Spalte auf dem Tisch t namens serial, die verwendet werden können, das relative Alter der Zeilen zu bestimmen:

CREATE TRIGGER ten_rows_only AFTER INSERT ON t 
    BEGIN 
    DELETE FROM t WHERE serial <= (SELECT serial FROM t ORDER BY serial DESC LIMIT 10, 1); 
    END; 

das wird nichts tun, wenn Sie weniger als zehn Zeilen, und die niedrigsten Serien DELETE, wenn ein INSERT Sie elf Reihen schieben würde.

UPDATE

Hier ist ein etwas komplizierter Fall, wo Ihre Tabellensätze „Alter“ der Zeile in einer Spalte, die Duplikate, wie zum Beispiel einer TIMESTAMP Spalte Verfolgung der Einsatzzeiten enthalten.

sqlite> .schema t 
CREATE TABLE t (id VARCHAR(1) NOT NULL PRIMARY KEY, ts TIMESTAMP NOT NULL); 
CREATE TRIGGER ten_rows_only AFTER INSERT ON t 
    BEGIN 
    DELETE FROM t WHERE id IN (SELECT id FROM t ORDER BY ts DESC LIMIT 10, -1); 
    END; 

Hier nehmen wir für selbstverständlich, dass wir nicht id relatives Alter zu bestimmen, verwenden können, so dass wir alles nach den ersten 10 Reihen durch Zeitstempel bestellt löschen. (SQLite erzwingt eine beliebige Reihenfolge in Zeilen, die dasselbe teilen ts).

+0

würde dies nicht immer löschen Sie die erste Zeile zu implementieren? – aronchick

+0

@aronchick, nein - die skalare Unterabfrage wird auf NULL ausgewertet, wenn an der elften Stelle kein Datensatz vorhanden ist (NACH UNSERER INSERT möglicherweise der 11. Zeile) und die 'WHERE'-Klausel dann zu' WHERE serial <= NULL wird, das wird nichts zusammenbringen. – pilcrow

+0

Was passiert, wenn die _id automatisch inkrementiert wird? Könnte dieser Code nicht mit der _id statt TIMESTAMP oder seriell durchgeführt werden? Vor allem, wenn ein TIMESTAMP nicht immer Teil des Tabellenschemas ist ... –

0

Das wäre etwas wie, wie Sie es tun würden. Dies setzt voraus, dass my_id_column automatisch inkrementiert und die Sortierspalte für die Tabelle ist.

-- handle rolls forward 
-- deletes the oldest row 
create trigger rollfwd after insert on my_table when (select count() from my_table) > max_table_size 
    begin 
    delete from my_table where my_id_column = (select min(my_id_column) from my_table); 
    end; 

-- handle rolls back 
-- inserts an empty row at the position before oldest entry 
-- assumes all columns option or defaulted 
create trigger rollbk after delete on my_table when (select count() from my_table) < max_table_size 
    begin 
    insert into my_table (my_id_column) values ((select min(my_id_column) from my_table) - 1); 
    end; 
Verwandte Themen