2009-12-29 13 views
10

Vorrei creare una tabella SQL che abbia non più di n righe di dati. Quando viene inserita una nuova riga, vorrei rimuovere la riga più vecchia per fare spazio a quella nuova.Rolling rows in SQL table

Esiste un modo tipico di gestirlo all'interno di SQLite?

Dovrebbe gestirlo con un codice esterno (di terze parti)?

risposta

11

Ampliando Alex' answer, e supponendo che si hanno un'incrementazione, non ripetibile colonna di serie sul tavolo t denominata serial che può essere usato per determinare l'età relativa delle righe:

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; 

Questo non farà nulla quando si hanno meno di dieci righe, e si DELETE il serial più basso quando un INSERT si spingerebbe a undici righe.

UPDATE

Ecco un caso un po 'più complicato, dove i vostri tavolo record "età" di riga in una colonna che può contenere duplicati, come ad esempio una colonna TIMESTAMP il monitoraggio dei tempi di inserimento.

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; 

Qui diamo per scontato che non possiamo usare id per determinare l'età relativa, così abbiamo eliminare tutto dopo le prime 10 righe in ordine di data e ora. (SQLite impone un ordine arbitrario su righe che condividono lo stesso ts).

+0

non sarebbe questa eliminare sempre la prima fila? – aronchick

+0

@aronchick, no - la sottoquery scalare valuterà su NULL se non c'è nessun record in undicesima posizione (DOPO il nostro INSERT di possibilmente l'undicesima riga), quindi la clausola 'WHERE' diventa' WHERE serial <= NULL', che non corrisponderà a nulla. – pilcrow

+0

Cosa fare se _id viene incrementato automaticamente. Non è possibile eseguire questo codice con _id anziché TIMESTAMP o seriale? Soprattutto quando un TIMESTAMP non fa sempre parte dello schema della tabella ... –

0

Questo sarebbe qualcosa come come lo faresti. Ciò presuppone che my_id_column si incrementi automaticamente e sia la colonna di ordinamento per la tabella.

-- 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;