限制房间数据库中的行数

39

如何限制 Android Room 数据库的行数,通过删除最旧的一行并插入最新的行来实现?

我猜想这是在向数据库添加项目时使用的标准查询吗?

编辑:我希望将数据表限制为最多包含 20 行。如果达到该限制,则需要删除最旧的项目并插入最新的项目,从而保持当前行数为 20。


1
你能解释一下你想要什么吗?你想要为数据库行设置限制,当你想要添加新数据时,如果所有行都有旧数据,那么数据库会将你的新数据添加到第一行吗?还是你会选择特定的行来设置数据? - Mohamed Nagy Mostafa
@MohamedNagyMostafa 请查看编辑。 - Stillie
好的.. 我认为有两种方法可以做到这一点,首先我可以告诉你一种技巧,连续插入新数据从1到20,所有行都有数据,然后再重复插入从1开始... 但是,如果您不打算在程序中删除行,则这将是一个很好的方法。因为如果您删除任何行,则最好的算法是将新数据设置在已删除的行中。第二种方法是,如果您的程序中有删除行,则必须使用列来插入日期,然后可以通过排序检查它的检索数据。请告诉我哪个对您有好处,我会详细解释。 - Mohamed Nagy Mostafa
5个回答

32

这里是一个示例解决方案:

查询为:

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

这里将根据限制和偏移量列出用户。

如果 loadAllUsersByPage(2,0),它将从表中返回前2行。

如果 loadAllUsersByPage(2,1),它将返回表中的第2行和第3行。

但是,如果 loadAllUsersByPage(-1,10),则将提供表中的前10行。


如果您将Integer.MAX_VALUE作为限制条件传递,那么与没有LIMIT子句的查询相比,性能会更差吗? - Mark
@Mark,从技术上讲-是的,因为强制限制可能在内部意味着对数据集进行某种形式的排序,这会影响性能。数据库查询允许使用超过任何MAX_VALUE(包括超过Long.MAX_VALUE)的值,因此它们通常不会在限制和偏移量中赋予Integer.MAX_VALUE任何特殊含义。 - M. Prokhorov
在数据库中创建表是否有限制?我是说一个数据库可以创建多少个表?一个数据库可以创建多少行?有什么限制吗? - Wini

30

我认为您可以将数据插入到表中,然后删除除了最后20条以外的所有行(使用limit)

若要删除,您可以使用以下查询语句:

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

在这种情况下,id是主键,其被设置为自动递增。如果您按日期存储数据,也可以使用日期作为键。


3
这将实际上删除多达25行,而原帖中尝试保留不超过25行 - M. Prokhorov
1
在数据库中创建表有什么限制吗?我的意思是一个数据库可以创建多少个表?一个数据库可以创建多少行?有限制吗? - Wini
@Wini 请查看https://www.sqlite.org/limits.html。 - Kunu

4
你可以通过以下方法限制列/行:此查询将在达到其限制时返回新数据并删除旧数据。
解释:
  1. 第一个查询是按降序选择所有数据
  2. 第二个查询是从列/行ID > 20中删除数据
如果您希望您的表只有20行,则将OFFSET设置为20,LIMIT表示一次插入和删除多少行。
在我的示例中,当用户输入1个新数据时,我会删除1行(最旧/最后的行)。

  @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()

2
假设:
您的表格如下:
    create table example_table (
      ts timestamp,
      uid number(19),
      some_other_field varchar(64)
    );

如果你不想手动运行一些查询,可以使用数据库触发器:

    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;

"

无限偏移量" 语法受到这个答案的启发。

要在Java中启用触发器:

可以覆盖SQLiteOpenHelper的Simple Android:

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

Android Room 版本:

     public class MyDatabase extends RoomDatabase {
       @Override
       public void init(DatabaseConfiguration _config) {
         super.init(_config);
         getOpenHelper().getWritableDatabase().execSQL(<trigger string from above>);
       }
     }

我正在使用Android Room来处理SQL数据库。 - Stillie
1
@x10sion,你仍然可以做到,只是在稍微不同的地方。我会把这个加入我的答案中。 - M. Prokhorov
@x10sion,这对你有用吗?(我自己并不太熟悉Room) - M. Prokhorov

0

按照以下步骤:

1> 获取该表的行数

your_count = SELECT count( * ) FROM table_name;

2> 如果计数大于20,则获取最旧的记录

SELECT *
  FROM table_name
 ORDER BY entry_Date ASC
 LIMIT 1;

3> 现在删除这些选定的记录

4> 插入新数据

注意:如果您要插入多个条目,请将其放入循环中


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接