问题
This is a simple question.
Background
I'm supposed to have max of 400 rows in some table, based on timestamp field, so old ones will be removed automatically. For here, let's say it's 3 instead.
The table has various fields, but the timestamp is what's important here.
The problem
Even though I've succeeded (looked here), for some reason it got me to a max of an additional item, so I just adjusted it accordingly. This means that instead of 3, I got 4 items.
private const val MAX_ITEMS = 3
private val TIMESTAMP_FIELD = "timestamp"
private val DELETE_FROM_CALL_LOG_TILL_TRIGGER =
String.format(
"CREATE TRIGGER %1\$s INSERT ON %2\$s
WHEN (select count(*) from %2\$s)>%3\$s
BEGIN
DELETE FROM %2\$s WHERE %2\$s._id IN " +
"(SELECT %2\$s._id FROM %2\$s ORDER BY %2\$s.$TIMESTAMP_FIELD DESC LIMIT %3\$d, -1);
END;"
, "delete_till_reached_max", TABLE_NAME, MAX_ITEMS - 1)
What I've tried
I tried :
- Change the condition to just being insertion (meaning without the
WHEN
part) - Change
LIMIT %3\$d, -1
toLIMIT -1 OFFSET %3\$d
. Also tried a different number than "-1" (tried 0, because I thought it's extra).
The questions
- How come I had to use
MAX_ITEMS - 1
instead of justMAX_ITEMS
? Why does it leave me with 4items instead of 3 ? - Does it matter if I have
WHEN
there? Is it better?
回答1:
- You have omitted the
BEFORE | AFTER
clause, so it'sBEFORE
by default. This means you are counting the rows before the insert, not after it. - This depends. At first, when the table has not reached the limit yet, the quick count lookup may save you some time, as you avoid the more complicated delete. But as soon as the table is full, you'll have to delete anyway, so counting is just additional work to do.
This should work:
private const val MAX_ITEMS = 3
private val TIMESTAMP_FIELD = "timestamp"
private val DELETE_FROM_CALL_LOG_TILL_TRIGGER =
String.format(
"CREATE TRIGGER %1\$s AFTER INSERT ON %2\$s
FOR EACH ROW
BEGIN
DELETE FROM %2\$s WHERE _id =
(SELECT _id FROM %2\$s ORDER BY %4\$s DESC LIMIT 1 OFFSET %3\$s);
END;"
, "delete_till_reached_max", TABLE_NAME, MAX_ITEMS, TIMESTAMP_FIELD)
Once there are 400 rows in the table, you can just as well call the trigger something like trg_keep_rowcount_constant
and remove GROUP BY null HAVING COUNT(*) > %3\$s
from the code.
Demo: https://dbfiddle.uk/?rdbms=sqlite_3.27&fiddle=ea3867e20e85927a2de047908771f4f1
来源:https://stackoverflow.com/questions/62242272/how-to-set-a-max-items-for-a-specific-table-using-trigger-in-sqlite