SQLite存储数据(小细节)

本文介绍了在Android中使用SQLite数据库的两种主要方法:通过`openOrCreateDatabase`方法直接创建及通过继承`SQLiteOpenHelper`类创建数据库。此外还提供了判断表是否存在、使用Android SDK自带的sqlite3工具进行数据库管理的方法。

打开SQLite 数据库两种方式: 

通过openOrCreateDatabase(String path, SQLiteDatabase.CursorFactory factory)方法创建数据库。

   1 SQLiteDatabase db =this.openOrCreateDatabase("test_db.db", Context.MODE_PRIVATE, null);
   2 SQLiteDatabase db2 = SQLiteDatabase.openOrCreateDatabase("/data/data/com.test/databases/test_db2.db3", null);
 如上两种方式均能创建数据库,this.openOrCreateDatabase是对SQLiteDatabase.openOrCreateDatabase而来,如代码所见,原生的SQLiteDatabase.openOrCreateDatabase()方法第一参数要求输入绝对路劲,而所有的数据库都是储存于“data/data/应用报名/databases”目录下,所以输入完全的绝对路劲是一件重复且繁杂的工作。采用this.openOrCreateDatabase则省去了此操作。执行操作后的结果如下图:
 

另外还可以通过写一个继承SQLiteOpenHelper类的方式创建数据库,此种方式是一种更加进阶的创建方式,所以在此不做描述。

Android SQLite数据库判断某张表是否存在的语句:
1、可以在创建表之前判断,这样就不会重新创建,create table if not exists Student(name text primary key, code integer); 比平时多了if not exists
2、String sql = "select name from sqlite_master where type='table';";
Cursor cursor = db.rawQuery(sql, null);
  while(cursor.moveToNext()){
   //遍历出表名
   String name = cursor.getString(0);
   Log.i("System.out", name);
  }
3、String sql = "select count(*) as c from sqlite_master where type ='table' and name ='Student';";
Cursor cursor = db.rawQuery(sql, null);
    if(cursor.moveToNext()){
          int count = cursor.getInt(0);
          if(count>0){
               result = true;
           }
     }

Android sqlite3数据库管理工具

Android SDK的tools目录下提供了一个sqlite3.exe工具,这是一个简单的sqlite数据库管理工具。开发者可以方便的使用其对sqlite数据库进行命令行的操作。

 

程序运行生成的*.db文件一般位于"/data/data/项目名(包括所处包名)/databases/*.db",因此要对数据库文件进行操作需要先找到数据库文件:

1、进入shell 命令

adb shell

 

2、找到数据库文件

#cd data/data

#ls                --列出所有项目

#cd project_name   --进入所需项目名

#cd databases    

#ls                --列出现寸的数据库文件

 

3、进入数据库

#sqlite3 test_db   --进入所需数据库

会出现类似如下字样:

SQLite version 3.6.22

Enter ".help" for instructions

Enter SQL statements terminated with a ";"

sqlite>

至此,可对数据库进行sql操作。

 

4、sqlite常用命令

>.databases        --产看当前数据库

>.tables           --查看当前数据库中的表

 

>.help             --sqlite3帮助

<think>我们面对的问题:如何在Android SQLite中,当存储大小达到一定程度后,自动删除其中十分之一的数据? 思路: 1. 首先我们需要判断数据库的当前大小。SQLite数据库在Android中通常存储为一个文件(在/data/data/<package_name>/databases/目录下)。 2. 我们可以通过获取该数据库文件的大小来判断存储大小。 3. 设定一个阈值(比如100MB),当数据库文件大小超过这个阈值时,触发删除操作。 4. 删除操作:我们需要删除数据库中十分之一的数据。注意,删除哪些数据?这需要根据业务逻辑来定。通常,我们会删除最旧的数据(按照时间戳或自增ID排序),或者根据其他策略(如使用频率最低等)。这里假设我们按照时间戳排序,删除最早插入的10%的数据。 步骤: a. 获取数据库文件大小。 b. 检查是否超过阈值。 c. 如果超过,则执行删除操作。 具体实现: 1. 获取数据库文件大小: File dbFile = context.getDatabasePath("your_database_name.db"); long size = dbFile.length(); // 单位是字节 2. 设定阈值(例如100MB): long threshold = 100 * 1024 * 1024; // 100MB 3. 当size > threshold时,执行删除操作。 4. 删除操作: - 首先,我们需要知道总数据条数(假设表名为MyTable): SELECT COUNT(*) FROM MyTable; - 计算需要删除的数据条数:totalRows / 10(向上取整或向下取整,根据需求) - 然后,按照时间戳(假设字段名为timestamp)排序,删除最早的(即时间戳最小的)那部分数据。 DELETE FROM MyTable WHERE id IN (SELECT id FROM MyTable ORDER BY timestamp ASC LIMIT ?); 注意:这里我们使用了子查询,LIMIT后面是要删除的条数。 但是,这里有一个问题:如果数据量很大,删除操作可能会耗时,导致主线程阻塞。因此,我们需要在后台线程执行。 5. 另外,删除操作完成后,我们可能还需要执行VACUUM命令来释放空间(但注意VACUUM会重新整理数据库文件,可能会耗时较长,且需要独占数据库)。 6. 另一种删除策略:如果我们有一个自增的ID字段,我们可以记录上次删除时的最大ID,然后删除比这个ID小且是前10%的数据。但是这里我们按照时间戳排序。 考虑到性能,我们可能不需要每次都执行COUNT(*)查询,因为当数据量非常大的时候,COUNT(*)可能会慢。我们可以考虑定期执行这个操作(比如每次插入新数据时检查,或者每天检查一次等)。 示例代码: 假设我们有一个表MyTable,字段包括:_id(主键),timestamp(记录插入时间,或者最后修改时间,我们按插入时间算),以及其他字段。 在插入数据后,我们可以检查数据库大小,如果超过阈值,则启动异步任务执行删除: ```java public class MyDatabaseHelper extends SQLiteOpenHelper { private static final String DB_NAME = "my_db.db"; private static final int DB_VERSION = 1; private static final long THRESHOLD = 100 * 1024 * 1024; // 100MB public MyDatabaseHelper(Context context) { super(context, DB_NAME, null, DB_VERSION); } // 在插入数据后调用此方法 public void checkAndDeleteOldData(Context context) { File dbFile = context.getDatabasePath(DB_NAME); long dbSize = dbFile.length(); if (dbSize > THRESHOLD) { // 在后台线程执行删除 new DeleteOldDataTask().execute(); } } private class DeleteOldDataTask extends AsyncTask<Void, Void, Void> { @Override protected Void doInBackground(Void... voids) { SQLiteDatabase db = getWritableDatabase(); // 计算总行数 Cursor cursor = db.rawQuery("SELECT COUNT(*) FROM MyTable", null); int totalRows = 0; if (cursor != null) { if (cursor.moveToFirst()) { totalRows = cursor.getInt(0); } cursor.close(); } // 计算要删除的行数(这里是删除10%) int rowsToDelete = (int) Math.ceil(totalRows * 0.1); if (rowsToDelete > 0) { // 执行删除:删除最早插入的rowsToDelete条记录 db.execSQL("DELETE FROM MyTable WHERE _id IN (SELECT _id FROM MyTable ORDER BY timestamp ASC LIMIT ?)", new Object[]{rowsToDelete}); // 注意:这里假设timestamp字段记录了插入时间,并且是按升序排列(最小的时间戳是最早插入的) // 删除后,可以执行VACUUM来释放空间,但VACUUM会占用较多时间和资源,需谨慎使用 // db.execSQL("VACUUM"); } return null; } } } ``` 注意: - 上述代码中,我们使用了AsyncTask来在后台执行删除操作,避免阻塞UI线程。 - 删除操作使用了一个子查询,找出时间戳最小的前rowsToDelete条记录,然后删除。 - VACUUM命令可以释放删除后留下的空间,但会导致数据库文件重组,耗时较长。如果对实时性要求高,可以定期在合适时机(比如应用启动时)执行VACUUM。 另外,也可以考虑使用SQLite的DELETE结合LIMIT子句(注意:在SQLite中,DELETE语句可以直接使用LIMIT,但是这里我们使用了子查询,因为WHERE条件中需要指定哪些行)。 但是,请注意:上述删除逻辑依赖于timestamp字段,并且假设该字段是单调递增的(即后插入的数据时间戳更大)。如果数据的时间戳可能被修改,那么就不能代表插入时间了。 如果表中有自增主键(通常如此),我们可以使用自增主键来替代时间戳,因为自增主键可以反映插入顺序(但不绝对,如果删除过数据,自增主键可能不连续,但通常新插入的数据自增ID比老数据大)。这样我们就可以按照主键排序。 修改后的删除语句: DELETE FROM MyTable WHERE _id IN (SELECT _id FROM MyTable ORDER BY _id ASC LIMIT ?); 这样就不需要依赖时间戳字段了。 总结: 1. 监控数据库文件大小。 2. 超过阈值后,在后台删除最旧的10%的数据(按插入顺序,使用自增主键或时间戳)。 3. 删除操作在后台线程执行,避免阻塞主线程。 4. 慎重使用VACUUM,因为它会锁住数据库并重新整理,可能会影响应用性能。 注意事项: - 实际应用中,阈值大小需要根据设备存储空间和业务需求合理设置。 - 删除策略(如删除最旧的数据)可能不适用于所有业务场景,可能需要根据具体需求调整(例如删除访问频率最低的数据等)。 - 频繁检查数据库大小可能会影响性能,可以考虑在插入数据时抽样检查,或者定时检查。 相关问题: 1. 如何优化SQLite数据库的删除操作性能? 2. 除了删除旧数据,还有哪些方法可以控制SQLite数据库的大小? 3. 在Android中执行VACUUM命令的最佳实践是什么? 4. 如何确保删除操作不会影响应用的其他数据库操作(例如使用事务)? </think>### Android SQLite存储大小管理:删除十分之一数据的方法 在Android中使用SQLite时,当数据库达到预设存储大小时自动删除10%数据,可通过以下步骤实现: #### 1. **监控数据库大小** - 获取数据库文件大小: ```java File dbFile = context.getDatabasePath("your_database.db"); long dbSize = dbFile.length(); // 单位:字节 ``` - 设定阈值(例如100MB): ```java long threshold = 100 * 1024 * 1024; // 100MB ``` #### 2. **删除策略实现(删除最早10%的数据)** ```java public void deleteOldest10Percent(SQLiteDatabase db) { // 步骤1:获取总数据量 Cursor cursor = db.rawQuery("SELECT COUNT(*) FROM your_table", null); cursor.moveToFirst(); int totalRows = cursor.getInt(0); cursor.close(); // 步骤2:计算需删除的行数(10%) int rowsToDelete = (int) Math.ceil(totalRows * 0.1); if (rowsToDelete > 0) { // 步骤3:按时间戳排序并删除最早数据 db.execSQL("DELETE FROM your_table WHERE id IN (" + "SELECT id FROM your_table " + "ORDER BY timestamp_column ASC LIMIT ?)", new Object[]{rowsToDelete}); // 可选:执行VACUUM回收空间 db.execSQL("VACUUM"); } } ``` #### 3. **触发删除的完整流程** ```java public void checkAndCleanDatabase(Context context) { SQLiteDatabase db = getWritableDatabase(); File dbFile = context.getDatabasePath("your_database.db"); if (dbFile.length() > THRESHOLD) { // 在后台线程执行删除 new Thread(() -> { deleteOldest10Percent(db); Log.d("DB_CLEAN", "Deleted 10% of oldest records"); }).start(); } } ``` #### 关键细节说明 1. **排序字段选择**: - 使用`timestamp_column`(如插入时间)确保删除最早数据 - 替代方案:使用自增ID列`ORDER BY _id ASC` 2. **性能优化**: - 事务处理:批量删除时启用事务 ```java db.beginTransaction(); try { // 删除操作 db.setTransactionSuccessful(); } finally { db.endTransaction(); } ``` - 索引优化:为排序字段(如时间戳)创建索引 3. **空间回收**: - `VACUUM`命令可减少文件碎片,但会暂时锁定数据库[^3] - 替代方案:定期在应用空闲时执行`VACUUM` 4. **扩展场景**: - SD卡存储:若数据库在SD卡需检查存储状态[^4] - 多表处理:对关联表使用`ON DELETE CASCADE` > **提示**:此方案适用于日志、缓存等时序数据场景。对于关键业务数据,建议采用备份迁移策略而非直接删除。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值