列举了 sqlite 数据库的基本操作
文章目录
- 一、数据库
- 1.1 定义
- 1.2 获取(包括了创建、升级、降级)
- 二、表
- 2.1 定义
- 2.2 操作
- 2.2.1 创建表
- 2.2.2 修改表
- 2.2.3 删除表
- 三、数据
- 3.1 定义
- 3.2 操作
- 3.2.1 增
- 3.2.2 删
- 3.2.3 改
- 3.2.4 查
- 四、运行
- 五、获取数据库文件
一、数据库
1.1 定义
通过 SQLiteOpenHelper 来定义一个 数据库。一般会在 onCreate() 中执行创表语句,生成数据库内的表。
public class ChinaDbHelper extends SQLiteOpenHelper {
public ChinaDbHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
}
@Override
public void onCreate(SQLiteDatabase db) {
...
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
@Override
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
super.onDowngrade(db, oldVersion, newVersion);
}
}
1.2 获取(包括了创建、升级、降级)
通过 SQLiteOpenHelper.getWritableDatabase 来获取一个数据库,在 getWritableDatabase 中会调数据库的 onCreate() 、onUpgrade()、onDowngrade() 方法。
public void accessDB() {
ChinaDbHelper chinaDbHelper = new ChinaDbHelper(this, "china.db", null, 1);
// getWritableDatabase 时会调 onCreate、onUpgrade、onDowngrade
chinaDb = chinaDbHelper.getWritableDatabase();
}
- onCreate:创建回调
在第一次调用 getWritableDatabase 时回调。 - onUpgrade:升级回调
在 version 变高,调用 getWritableDatabase 时回调。 - onDowngrade:降级回调
在 version 变低,调用 getWritableDatabase 时回调。
二、表
2.1 定义
通过 sql 语句定义。
一个名为 city1,列为 id、city_id,主键为 id,主键自增长的表:
city1 (id integer primary key autoincrement, city_id text)
2.2 操作
2.2.1 创建表
创建 city1、city2 表
public void createTable() {
String createCity1 = "create table city1 (" +
"id integer primary key autoincrement, " +
"city_id text)";
chinaDb.execSQL(createCity1);
String createCity2 = "create table city2 (" +
"id integer primary key autoincrement, " +
"city_id text)";
chinaDb.execSQL(createCity2);
}
2.2.2 修改表
更新 city1 表名至 city
给 city 中增加一列 city_name
public void updateTable() {
String renameTable = "alter table city1 rename to city";
chinaDb.execSQL(renameTable);
String addColumn = "alter table city add column city_name text";
chinaDb.execSQL(addColumn);
}
2.2.3 删除表
删除 city2 表
public void deleteTable() {
String deleteTable = "drop table city2";
chinaDb.execSQL(deleteTable);
}
删除所有表
其中 sqlite_sequence 表是 SQLite 的系统表。该表用来保存其他表的自增 id 最大值,删了会报错。
sqlite_master 也是 SQLite 的系统表。保存了所有表、索引的信息。
public static void deleteAllTable() {
List<String> list = getAllTable();
for (String s : list) {
if ("sqlite_sequence".equals(s)) {
continue;
}
String deleteTable = "drop table " + s;
chinaDb.execSQL(deleteTable);
}
}
// 获取库中所有表
public static List<String> getAllTable() {
List<String> tables = new ArrayList<>();
String getAllTable = "select name from sqlite_master where type='table' order by name";
Cursor cursor = chinaDb.rawQuery(getAllTable, null);
while (cursor.moveToNext()) {
tables.add(cursor.getString(0));
}
cursor.close();
return tables;
}
三、数据
3.1 定义
public class City {
private int id;
private String cityId;
private String cityName;
3.2 操作
3.2.1 增
插入一条数据
public void insertCity(City city) {
ContentValues values = new ContentValues();
values.put("city_id", city.getCityId());
values.put("city_name", city.getCityName());
chinaDb.insert("city", null, values);
}
3.2.2 删
删除一条数据
public void deleteCity(City city) {
chinaDb.delete("city", "city_id = ?", new String[]{city.getCityId()});
}
3.2.3 改
更新一条数据
public void updateCity(City city) {
ContentValues values = new ContentValues();
values.put("city_name", city.getCityName());
chinaDb.update("city", values, "city_id = ?", new String[]{city.getCityId()});
}
3.2.4 查
获取所有数据
public List<City> getAllCity() {
List<City> list = new ArrayList<>();
Cursor cursor = chinaDb.rawQuery("select * from city", null);
while (cursor.moveToNext()) {
String cityId = cursor.getString(cursor.getColumnIndex("city_id"));
String cityName = cursor.getString(cursor.getColumnIndex("city_name"));
City city = new City(cityId, cityName);
list.add(city);
}
cursor.close();
return list;
}
获取某条数据
public City getCity(String cityId) {
Cursor cursor = chinaDb.rawQuery("select * from city where city_id = " + cityId, null);
if (cursor.moveToNext()) {
String _cityId = cursor.getString(cursor.getColumnIndex("city_id"));
String _cityName = cursor.getString(cursor.getColumnIndex("city_name"));
return new City(_cityId, _cityName);
}
cursor.close();
return null;
}
四、运行
public static void behave(Context context) {
accessDB(context);
deleteAllTable();
createTable();
Log.d(TAG, "after create table: " + getAllTable());
updateTable();
Log.d(TAG, "after update table: " + getAllTable());
deleteTable();
Log.d(TAG, "after delete table: " + getAllTable());
insertCity(new City("1", "北京"));
insertCity(new City("2", "上海"));
insertCity(new City("3", "广州"));
Log.d(TAG, "after insert: " + getAllCity());
City city = getCity("3");
city.setCityName("深圳");
updateCity(city);
Log.d(TAG, "after update: " + getAllCity());
deleteCity(city);
Log.d(TAG, "after delete: " + getAllCity());
}
输出:
D/database-sqlite: after create table: [city1, city2, sqlite_sequence]
D/database-sqlite: after update table: [city, city2, sqlite_sequence]
D/database-sqlite: after delete table: [city, sqlite_sequence]
D/database-sqlite: after insert: [City{id=0, cityId='1', cityName='北京'}, City{id=0, cityId='2', cityName='上海'}, City{id=0, cityId='3', cityName='广州'}]
D/database-sqlite: after update: [City{id=0, cityId='1', cityName='北京'}, City{id=0, cityId='2', cityName='上海'}, City{id=0, cityId='3', cityName='深圳'}]
D/database-sqlite: after delete: [City{id=0, cityId='1', cityName='北京'}, City{id=0, cityId='2', cityName='上海'}]
五、获取数据库文件
数据库文件位于 /data/data/包名/databases
目录
- 通过 Device File Explorer
SQLiteDatabase 默认读写模式是 TRUNCATE
,该模式下读写都必须同步。它会使用 journal 文件作为辅助。这时在 data 目录下看到的就是 db 和 db-journal。db 内就是最新数据。如上图所示。
当调用了 SQLiteDatabase 的 enableWriteAheadLogging() 方法,会将读写模式设为 WAL(write-ahead log)
,该模式下读可以并发,写必须同步。它会使用 shm、wal 文件作为辅助。这时在 data 目录下看到的是 db、db-shm、db-wal。db 内不一定是最新数据(可能还在 wal 文件中)。如下图所示。
关于读写模式,可见这里 和这里。
- 通过 adb
adb exec-out run-as com.gdeer.gdtesthub cat /data/data/com.gdeer.gdtesthub/databases/china.db > china.db