Question

I successfully used the following BEFORE INSERT trigger to limit the number of rows stored in the SQLite database table locations. The database table acts as a cache in an Android application.

CREATE TRIGGER 'trigger_locations_insert'
BEFORE INSERT ON 'locations'
WHEN ( SELECT count(*) FROM  'locations' ) > '100'
  BEGIN
    DELETE FROM 'locations' WHERE '_id' NOT IN
    (
      SELECT '_id' FROM 'locations' ORDER BY 'modified_at' DESC LIMIT '100' 
    );
  END

Meanwhile, I added a second trigger that allows me to INSERT OR UPDATE rows. - The discussion on that topic can be found in another thread. The second trigger requires a VIEW on which each INSERTis executed.

CREATE VIEW 'locations_view' AS SELECT * FROM 'locations';

Since an INSERT is no longer executed on the TABLE locations but on the VIEW locations_view, the above trigger does no longer work. If I apply the trigger on the VIEW the following error message is thrown.

Failure 1 (cannot create BEFORE trigger on view: main.locations_view)

Question:

How can I change the above trigger to observe each INSERT on the VIEW - or do you recommend another way to limit the number of rows? I would prefer to handle this kind of operation within the database, rather then running frontend code on my client.


Performance issues:

Although, the limiter (the above trigger) works in general - it performs less then optimal! Actually, the database actions take so long that an ANR is raised. As far as I can see, the reason is, that the limiter is called every time an INSERT happens. To optimize the setup, the bulk INSERT should be wrapped into a transaction and the limiter should perform right after. Is this possible? If you like to help, please place optimization comments concerning the bulk INSERT into the original question. Comments regarding the limiter are welcome here.

Était-ce utile?

La solution

This type of trigger should work fine in conjunction with the other one. The problem appears to be that the SQL is unnecessarily quoting the _id field. It is selecting the literal string "_id" for every row and comparing that to the same literal string.

Removing the quotes around '_id' (both in the DELETE and in the sub-SELECT) should fix the problem.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top