在Android中使用最多的就是SQLiteOpenHelper,这篇文章会从SQLiteOpenHelper入手,讲述一下SQLiteOpenHelper的用法,以及相关的调试。
建立数据库
首先需要建立一个类继承SQLiteOpenHelper
public class MySql extends SQLiteOpenHelper {
/**当数据库不存在时,就会创建数据库,然后打开数据库,再调用onCreate 方法来执行创建表之类的操作。
* 当数据库存在时,SQLiteOpenHelper 就不会调用onCreate方法了,
* 若传入的版本号高于当前的,就会执行onUpgrade()方法来更新数据库和版本号。
* @param context
* @param name 表示数据库文件名(不包括文件路径,默认路径是/data/data/包名/databases),SQLiteOpenHelper类会根据这个文件名来创建数据库文件。
* @param factory 数据库进行查询的时候会返回一个cursor,这个cursor就是actory中产生的,factory可以进行自定义
* @param version 表示数据库的版本号。如果当前传入的数据库版本号比上一次创建的版本高,SQLiteOpenHelper就会调用onUpgrade()方法。
*/
public MySql(Context context, String name,
CursorFactory factory, int version) {
super(context, name, factory, version);
}
/**当数据库首次创建时执行该方法,一般将创建表等初始化操作放在该方法中执行.
*
* @param sqLiteDatabase
*/
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
sqLiteDatabase.execSQL("create table if not exists person("
+ "id integer primary key,"
+ "name text,"
+ "sex text)");
}
/**当打开数据库时传入的版本号与当前的版本号不同时会调用该方法
* @param sqLiteDatabase
* @param oldVersion
* @param newVersion
*/
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
}
}复制代码
每一个参数的含义,可以参照我写的注释。
我在这里通过执行sql语句"create table if not exists person(id integer primary key,name text,sex text)"
创建了一个表。表名是person。
我们写一个Activity,用来创建这个表:
MySql mySql ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mySql = new MySql(this,"test.db",null,1);
}复制代码
表名是test.db 版本号为1。
查看表的结构
如何查看表的结构呢?有以下几种办法(如果是真机,都需要是一个root的手机):
SQLiteStudio
我们可以借助一些pc上的工具查看数据库的表结构。例如SQLiteStudio,当然还有其它软件,这里不再做介绍。
首先需要先将.db文件从手机中取出来,首先可以用adb pull
命令进入到手机存储中,切换到指定的文件夹(上面提到过在/data/data/包名/databases),然后将上面建立的test.db文件pull出来。
我一般使用的是Android monitor,点击一个按钮即可pull出来:
然后倒入到SQLiteStudio中进行查看,如下图所示
SQLScout
与上面的方法不同的是,这是一个AndroidStudio的插件,首先需要安装这个插件。然后修改一下工程配置:
首先是在工程的build.gradle中修改如下:
allprojects {
repositories {
jcenter()
maven {
url 'http://www.idescout.com/maven/repo/'
}
}
}复制代码
然后在module的build.gradle中添加:
compile 'com.idescout.sql:sqlscout-server:2.1'复制代码
或者去然后修改你使用的Activity:
SqlScoutServer.create(this, getPackageName());复制代码
重新运行即可。
在你安装完Android Studio插件后,IDE的右边会多一个:
点开,选择你的app:
操作
插入数据
首先需要获取SQLiteDatabase对象
SQLiteDatabase db = mySql.getWritableDatabase();复制代码
有两种方式可以进行数据插入,一种是执行原生的sql语句:
db.execSQL("insert into person(name,sex) values('deep','man')");复制代码
或者使用SQLiteDatabase提供的插入方法:
ContentValues values = new ContentValues();
values.put("name", "deep");
values.put("sex", "man");
db.insert("person", "id", values);复制代码
很多时候我们需要批量的向数据库中插入大量数据时,单独的使用添加方法导致应用响应缓慢, 因为sqlite插入数据的时候默认一条语句就是一个事务,有多少条数据就有多少次磁盘操作。
我们可以用beginTransaction()的方式用来标志开启事务,程序执行到endTransaction() 方法时会检查事务的标志是否为成功,如果程序执行到endTransaction()之前调用了setTransactionSuccessful() 方法设置事务的标志为成功则提交事务,如果没有调用setTransactionSuccessful() 方法则回滚事务。
同时可以配合insertOrThrow方法使用,判断是否插入成功。
db.beginTransaction();
try {
ContentValues cv = new ContentValues();
values.put("name", "deep");
values.put("sex", "man");
db.insertOrThrow("savedreports", null, cv);
db.setTransactionSuccessful();
} catch (SQLiteConstraintException e) {
return false;
} finally {
db.endTransaction();
}复制代码
选取数据
与上面的插入数据相同,也有如下几种方法
首先就是利用rawQuery方法:
SQLiteDatabase dbselect = mySql.getReadableDatabase();
Cursor cursor = dbselect.rawQuery("select * from "+"person", null);
while (cursor.moveToNext()) {
int id = cursor.getInt(0);
String name = cursor.getString(1);
String sex = cursor.getString(2);
Log.e("deep","id = "+id+" name= "+name+" sex="+sex);
}复制代码
查看log可以得到:
如果想指定id可以使用:
Cursor cursor = dbselect.rawQuery("select * from person where id=?", new String[]{"1"});复制代码
再有就是利用query方法:
Cursor cursor = dbselect.query("person",new String[]{"name,sex"}, "id=?", new String[]{"1"},null,null,null);
while (cursor.moveToNext()) {
String name = cursor.getString(0);
String sex = cursor.getString(1);
Log.e("deep"," name= "+name+" sex="+sex);
}复制代码
这个执行的意思是找到id = 1的一行,取出其中的name,和sex字段的值。
query(table,columns, selection, selectionArgs, groupBy, having, orderBy)方法各参数的含义:
- table:表名。相当于select语句from关键字后面的部分。如果是多表联合查询,可以用逗号将两个表名分开。
- columns:要查询出来的列名。相当于select语句select关键字后面的部分。
- selection:查询条件子句,相当于select语句where关键字后面的部分,在条件子句允许使用占位符“?”
- selectionArgs:对应于selection语句中占位符的值,值在数组中的位置与占位符在语句中的位置必须一致,否则就会有异常。
- groupBy:相当于select语句group by关键字后面的部分
- having:相当于select语句having关键字后面的部分
- orderBy:相当于select语句order by关键字后面的部分,如:personid desc, age asc;
删除数据
- 删除数据也是有两种,一种是使用原生的sql语句:
SQLiteDatabase dbdelete = mySql.getWritableDatabase();
dbdelete.execSQL("delete from person where id=1");复制代码
- 或者使用delete方法:
dbdelete.delete("person", "id=?", new String[]{"2"});复制代码
- 这个的意思是删除id = 2的一行。这里要注意,不是 new String[]{"2","3"}就是删除id等于2和3的两行,String数组的长度,要与前面的条件的数量对应。这里前面的条件是id=?这一个条件,所以String数组的长度只能为1。
dbdelete.delete("person", "1", null);
如果调用这个方法,表示删除所有行。
更新字段
更新字段也是有两种方式进行更新,第一种仍然是原生SQL:
SQLiteDatabase updatedb = mySql.getWritableDatabase();
updatedb.execSQL("update person set sex='woman' where id=4");复制代码
或者使用update方法:
ContentValues aaa = new ContentValues();
aaa.put("name", "deep");
aaa.put("sex", "woman");
updatedb.update("person",aaa,"id=?",new String[]{"6"});复制代码