38

How can I limit the number of rows in an Android room database by removing the oldest item in the row and inserting the newest one?

I am guessing its a standard query when adding an item to the database?

EDIT: I want to limit a database table to have a max row count of say 20. If that limit is reached, we remove the oldest item and insert the new one by keeping the current row count to 20.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Stillie
  • 2,647
  • 6
  • 28
  • 50
  • 1
    explain what you want ... you want set limits to your database rows and when you want to add new data and all rows have old data then database add your new data for first row ?? or you will choose specific row to set data ??? – Mohamed Nagy Mostafa Sep 13 '17 at 09:14
  • @MohamedNagyMostafa please see edit – Stillie Sep 13 '17 at 09:16
  • okey .. i think about two ways you can do it first i can tell you technique to insert new data continuously from 1 to 20 and all rows have data then repeat again to insert from 1 ... but it will be a good way id you are not going to delete rows during your program .. because if you delete any row then the best algorithm is to set the new data in the row which deleted. the second way if you have deleting row in your program you have to use column for insert date then you can check it by retrieve data by order sorting. tell my which one is good for you and i will explain it in detail – Mohamed Nagy Mostafa Sep 13 '17 at 09:32

5 Answers5

32

Here is a sample solution:

Query is :

@Query("SELECT * FROM user LIMIT :limit OFFSET :offset")
    User[] loadAllUsersByPage(int limit,int offset);

Here, it will list users based on limit and offset.

if loadAllUsersByPage(2,0) it will return the first 2 rows from the table.

if loadAllUsersByPage(2,1) it will return 2nd and 3rd rows from table.

but if loadAllUsersByPage(-1,10) then it will serve the first 10 rows from the table.

Md. Sajedul Karim
  • 6,749
  • 3
  • 61
  • 87
  • If you pass `Integer.MAX_VALUE` as the limit, will that be less performant than a query with no `LIMIT` clause? – Mark Feb 02 '19 at 07:40
  • @Mark, technically - yes, because imposing a limit could internally mean some form of sorting for dataset, which impacts performance. Database query is allowed to take more than any `MAX_VALUE` (including more than `Long.MAX_VALUE`), so they usually don't give any special meaning to `Integer.MAX_VALUE` in limit and offset. – M. Prokhorov Mar 18 '21 at 16:26
  • is there any limitations of creation of tables in db...i mean how much tables can be created in one db???n how much rows can be crated in one db?limitations? – Wini Mar 28 '21 at 09:17
30

I think you can insert the data into your table then remove all the rows except last 20 (limit)

To delete you can use the following query

DELETE FROM tableName where id NOT IN (SELECT id from tableName ORDER BY id DESC LIMIT 20)

In this case, id is the primary key which is set to auto increment. You can use date as key as well if you are storing them by date

Kunu
  • 5,078
  • 6
  • 33
  • 61
  • 3
    That will actually *delete up to 25 rows*, whereas OP tried to *retain no more than 25 rows*. – M. Prokhorov Sep 13 '17 at 09:37
  • 1
    is there any limitations of creation of tables in db...i mean how much tables can be created in one db???n how much rows can be crated in one db?limitations? – Wini Mar 28 '21 at 09:16
  • @Wini Check [https://www.sqlite.org/limits.html](https://www.sqlite.org/limits.html) – Kunu Mar 30 '21 at 05:10
3

You can limit columns/rows by doing this: this query will return the new data and remove old data when its reach its limit.

Explanation:

  1. First query is select all data order by descending
  2. Second query is remove data from columns/rows id > 20

If you want your table only have 20 row then set the OFFSET to 20, the LIMIT is represent how many rows inserted & deleted at once.

In my example I remove 1 row (the oldest/last row) when the user inputs 1 new data


  @Query("SELECT * FROM my_table ORDER BY timeStamp DESC")
  fun getAllData(): List<MyEntityClass>

  @Query("DELETE FROM my_table WHERE id IN (SELECT id FROM my_table ORDER BY timeStamp DESC LIMIT 1 OFFSET 20)")
  fun removeOldData()
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Muhammad Rio
  • 759
  • 5
  • 6
2

Assuming:

Your table is

    create table example_table (
      ts timestamp,
      uid number(19),
      some_other_field varchar(64)
    );

And you don't want to care about running some query manually.

Use database triggers:

    create trigger
      if not exists -- I don't actually know if you DB will support this line.
                    -- Might want to remove it if it's not.
    example_table_limiter
    on example_table
    after insert
    begin
      delete
      from example_table
      where ts in (
        select ts
        from example_table
        order by ts 
        limit -1 -- we don't want to limit how many rows we want to delete
        offset 25 -- but we want to offset query result so it leaves 25 rows in table
      );
    end;

"Offset without limit" syntax is inspired by this answer.

To enable your trigger in java:

Simple Android, where you can override SQLiteOpenHelper:

    public class DataBaseSchemaHelper extends SQLiteOpenHelper {
      @Override
      public void onCreate(SQLiteDatabase db) {     
        db.execSQL(<trigger string from above>);
      }
    }

Android Room version:

     public class MyDatabase extends RoomDatabase {
       @Override
       public void init(DatabaseConfiguration _config) {
         super.init(_config);
         getOpenHelper().getWritableDatabase().execSQL(<trigger string from above>);
       }
     }
M. Prokhorov
  • 3,894
  • 25
  • 39
0

Follow this steps :

1> get count of rows of that table

your_count = SELECT count( * ) FROM table_name;

2> if count is >(greater than) 20 than to get oldest record

SELECT *
  FROM table_name
 ORDER BY entry_Date ASC
 LIMIT 1;

3> now delete these selected records

4> insert new datas

NOTE : if you are inserting multiple entries than put this in loop

Amit Vaghela
  • 22,772
  • 22
  • 86
  • 142