一. 简介
SQLite 数据库是Android系统的内置数据库,数据库一般以文件的形式存放在/data/data/<your package name>/databases
路径下。
二. 使用方法
数据库的使用一般包括以下几个步骤
- 新建数据库
- 建表
- 插入数据
- 修改数据
- 删除数据
- 查询数据
下面我们结合代码来分步讲解数据库的使用方法:
在Android系统中,数据库的操作是通过一个databaseHelper 生成一个“数据库助手(dbHelper)” 通过这个助手的getWritableDatabase()
或者getReadableDatabase()
方法来获取一个数据库对象,(具体使用哪个方法,我们后面再详细进行解释)然后通过该数据库对象的内置方法进行对数据的“增删改查”操作。
1. 新建数据库
...
public class DBHelper extends SQLiteOpenHelper {
public DBHelper(@Nullable Context context, int version) {
super(context, "test.db", null, version);
}
/**
* 数据库初始化时调用
* @param db
*/
@Override
public void onCreate(SQLiteDatabase db) {
// 建表
db.execSQL("CREATE TABLE person (id INTEGER primary key autoincrement ,name varchar(64),address varchar(200),score INTEGER )");
}
/**
* 数据库版本更新时调用
* @param db
* @param oldVersion
* @param newVersion
*/
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
上面示例就是定义dbHelper的代码。定义一个自己的dbHelper ,继承自SQLiteOpenHelper
, 重写了onCreate
和onUpgrade
方法,顾名思义onCreate
方法是在数据库初始化的时候自动调用,一般在这个方法里完成建表的动作。而 onUpgrade
是在数据库版本号发生改变,数据库升级的时候自动调用。一般在该方法中完成对数据库升级更改,或者增加字段的功能。
另外在写自己的dbHelper时,一定要有一个带参数的构造方法。在构造方法的默认父类方法中定义数据库的名字,如上面示例中的 “test.db”。
2. 建表
当自定义的dbHelper写完以后,一般会在主函数中进行调用,如下:
...
private void initDatabase() {
DBHelper dbHelper = new DBHelper(this, 1);
db = dbHelper.getWritableDatabase();
tv_log.append("初始化数据库成功\n");
Log.i(TAG, "initDatabase: 初始化数据库");
}
...
在dbHelper.getWritableDatabase()
的时候就会调用 dbHelper的onCreate()
从而完成建表的动作。
这里要注意:dbHelper 有两个生成db对象的方法,一个是getWritableDatabase()
,另外一个是getReadableDatabase()
, 从字面意思就可以理解,一个生产的是一个可读可写的数据库对象,而另外一个生成的是只读的数据库对象。一般在对数据库进行查询的时候使用只读的数据库对象,而对数据库进行插入,删除,修改操作是,需要调用可读可写的数据库,所有一般图省事的话就直接调用getWritableDatabase()
方法就行了。
3. 插入数据
在前一步通过调用dbHelper的getWritableDatabase()
生成了一个db对象,那么直接通过调用db对象的insert
方法即可完成数据的插入动作。示例代码如下:
...
public void insert(View v) {
String name = "张三";
String address = "广东深圳";
int score = 90;
ContentValues values = new ContentValues();
values.put("name", name);
values.put("address", address);
values.put("score", score);
db.insert("person", null, values);
Log.i(TAG, "insert: 插入数据成功!");
}
...
注意 insert方法接收3个参数
- args1 String 要插入的表名
- args2 由于数据库中不允许插入空数据,所以万一args3 是空数据的话,就用null来替代插入数据库
- arg3 要插入到数据库中的数据,由ContentValues来构造。
4. 修改数据
同理,调用db的update方法进行数据的修改。示例代码如下:
...
public void update(View v) {
String id = et_id.getText().toString();
ContentValues values = new ContentValues();
values.put("score", 99);
// 将符合条件的字段数据进行更新
db.update("person", values, "id=?", new String[]{id});
tv_log.append("数据更新成功\n");
}
...
所谓的更新数据,肯定是对符合某些查询条件的数据进行更新,例如上例的id。update()
方法的参数详解如下:
- args1 String 要插入的表名
- args2 要更新的数据
- arg3 查询条件,类似于SQL语句中的
WHERE
关键字后面的额部分,参数用?
占位 - arg4 要查询条件的参数,一个String数组。因为查询条件可能会有多个限定条件和参数。
5. 删除数据
同理,调用db的delete方法进行数据的修改。示例代码如下:
...
public void delete(View v) {
// 将符合条件的字段数据进行更新
db.delete("person", "name=? AND score=?", new String[]{name, score});
}
...
核心代码就一句,delete方法的参数解释参照update方法。
6. 查询数据
查询数据相对来说比较复杂。先上代码,参照代码进行讲解:
public void query(View v) {
//table: 要查询的表名(String)
//columns: 要显示的字段名(String 数组)如果传null,代表所有字段全部显示
//selection: 查询条件(String),同“where” ,可以使用“and”和“or"等组合查询
//selectionArgs:需要查询的参数(String 数组)
// 剩下的参数一般是排序等条件,可以传null
String args_name = et_name.getText().toString();
Cursor cursor = db.query("person", null, "name=?", new String[]{args_name}, null, null, null);
if (cursor.moveToFirst()) {
// 注意这里有一个坑,好多教程都使用while循环,把cursor.moveToNext()作为判定条件,
// 结果一进来cursor就下移了一位,导致漏掉了第一组数据,所以这里一定要使用do...while循环。
do {
int id = cursor.getInt(cursor.getColumnIndex("id"));
String name = cursor.getString(cursor.getColumnIndex("name"));
String address = cursor.getString(cursor.getColumnIndex("address"));
int score = cursor.getInt(cursor.getColumnIndex("score"));
Log.i(TAG, "\nid : " + id
+ "\nname : " + name
+ "\naddress : " + address
+ "\nscore : " + score);
} while (cursor.moveToNext());
} else {
tv_log.append("数据未找到\n");
Log.i(TAG, "query: 该数据未找到");
}
cursor.close();
}
同样,也是调用db的query方法,query方法的参数详细解释可参见代码中的注释。其实只要理解了前面update和delete方法的参数构成,query的参数构造也就不难理解了。
调用query方法后会生成一个cursor,自己可以在脑海可以想象一下通过SQL语句查询以后数据库返回了一个类似于Excel表格的结果,这个cursor就好比一个小箭头,在整个表的左边,指向每一行数据,当当前条件查询到的数据为空的时候,结果就只是显示表头部分,这个时候cursor就位于表头,所以当判断cursor.moveToFirst()
时,cursor是无法移动的,只有当查询到有结果时,cursor才可以往上(表头方向)移动。这样通过if(cursor.moveToFirst())
作为判断条件来进行下一步的操作。
另外再说说这个cursor.movtToNext()
,这个函数是判断cursor是否还可以继续往下移动,从而判断查询结果是否还有数据,但是当调用一次moveToNext()
方法,cursor就已经向下移动了一位,那么第一行的数据就有可能没有读取,所以这里一定 要用do...while
循环来读取数据,确保第一行的数据也能被读取。
3. 总结
至此,关于Android自带的SQLite数据库的初级使用方法就介绍完了,整体的思路就是先有一个dbHelper,通过调用dbHelper的getWritableDatabase()
方法,生成一个db对象,然后通过db对象调用内置的insert()
,delete()
,update()
,query()
方法来完成对应的数据库的“增删改查”操作。