因为我现在在学数据库系统概论这门课,老师叫我们写一个对于数据库调用的小Demo,然后我就想到了可以用Android写一个记录班费开销的小程序,所以我就想借这个时机来对Android中数据库的运用来做一个记录以及复习。
言归正传
Android 为了让我们能够更加方便地管理数据库,专门提供了一个SQLiteOpenHelper 帮助类(抽象类),借助这个类就可以非常简单地对数据库进行创建和升级。
数据库的创建
在电脑是使用SQL Server我们先要对这个数据库进行创建,在Android中也是这样的,我们需要创建一个自己的帮助类去继承SQLiteOpenHelper帮助类,然后我们要实现里面的两个方法onCreate()和onUpgrade(),看名字就知道了,一个是对应的数据库的创建,另一个就是对应数据库的升级了(暂不说)。还记得我们在SQL Server用SQL语句对数据库基本表新建的代码是:
create table Class_daily(
id integer primary key,
cost_title varchar,
cost_date varchar,
cost_money varchar);
于是在Android中我们就可以在Oncreate方法中通过execSQL()方法传入这个字符串进行创建数据库以及Class_daily基本表:
//方便以后调用
public static final String COST_TITLE = "cost_title";
public static final String COST_DATE = "cost_date";
public static final String COST_MONEY = "cost_money";
public static final String TABLE = "Class_daily";
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table if not exists Class_daily("+
"id integer primary key,"+
"cost_title varchar,"+
"cost_date varchar,"+
"cost_money varchar);");
}
这样我们就把Class_daily表给创建好了,看字符串时我们觉得其实蛮简单的,但是如果自己打的时候就可以发现对字符串的拼接的时候很容易忘记把‘,’给忘了,并且最后的‘)’也容易和execSQL()方法后面的括号搞混了,所以我们一定要注意这一部分。
插入数据
表创建好了当然是要用来传数据的呀,所以我们就要新建一个方法来进行这样操作,我们要新建一个CostBean对象来传入数据,CostBean代码如下:
package com.xjh.gin.dailybook;
/**
* Created by Gin on 2017/12/5.
*/
public class CostBean {
public int id;
public String costTitle;
public String costDate;
public String costMoney;
}
然后我们把这些数据放入ContentValues中,并且写好对应的键名是什么,然后传入SQLiteDatabase的insert方法中,我们来看这个代码所需要传入的数据都代表什么:
public long insert(String table, String nullColumnHack, ContentValues values);
- String table 传入要插入的表名
- String nullColumnHack 代表强行插入null值的数据列的列名(没有就是null)
- ContentValues values 代表一行记录的数据
public void insertCost(CostBean costBean){
SQLiteDatabase database = getWritableDatabase();//获得数据库对象
ContentValues contentValues = new ContentValues();
contentValues.put(COST_TITLE,costBean.costTitle);
contentValues.put(COST_DATE,costBean.costDate);
contentValues.put(COST_MONEY,costBean.costMoney);
database.insert(TABLE,null,contentValues);
}
这样我们在方法中调用自己帮助类的insert方法传入一个自己自定义的类就可以把自己想要的数据进行插入了,把自定义类的值传入ContentValues对象中去。
删除数据
假如我们插入的数据有问题,或者因为一些情况不需要这条数据了,就想要在数据库中删除数据了,和SQL Server一样,我们需要传入要删除什么数据,我们来解释下delete方法的三个传入的值代表什么:
public int delete(String table, String whereClause, String[] whereArgs);
- String table 传入要插入的表名
- String whereClause 满足该whereClause子句的记录将会被删除
- String[] whereArgs 用于为whereArgs子句传入参数
我的例子就是传入id(id是主码),我们也可以传入一个类型的数据,我的代码是:
database.delete(TABLE, "id like ?", new String[]{"" + id});
说白了就是把id =“ ”分割成id = 和 “”。
?是占位符。
如果需要删除全部数据当然就是传入null咯,如下:
public void deleteAllData() {//一键清空
SQLiteDatabase database = getWritableDatabase();//获得数据库对象
database.delete(TABLE, null, null);//条件语句
}
这样我们就删除了所有数据了。
查询数据
我们用数据库存储值当然是需要用到才会存,所以我们使用数据就需要对我们所需要的数据进行查询,于是我们来说说在Android中怎么进行数据的查询的,我们先来看下query方法传入的值是什么意思
public Cursor query(boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit);
- boolean distinct 是否去除重复记录
- String table 传入要插入的表名
- String[] columns 需要查询的列名
- String selection 查询的条件子句
- String[] selectionArgs 用于为selection子句中占位符传入参数值,值在数组中的位置与占位符在语句中的位置必须一致,否则就会有异常
- String groupBy 控制分组
- String having 对分组进行过滤
- String orderBy 对查询出来的数据进行排序规则的定义
- String limit 用于进行分页
然后看下我代码中的例子吧。
public Cursor getAllCostData() {
SQLiteDatabase database = getWritableDatabase();//获得数据库对象
return database.query(TABLE, null, null, null, null, null, "cost_date " + "ASC");//null默认查询全部,ASC顺序排练
}
这个我们需要把数据库中的所有数据都要查询出来,所以除了表名和排序规则需要传入以外其他都为null,但是我们可以发现这个query和上面我们讲的query好像参数是不一样的,因为我们这个query方法内部是这样调用的,其实是自动赋了空值。
public Cursor query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy) {
return query(false, table, columns, selection, selectionArgs, groupBy, having, orderBy, null /* limit */);
}
然后我们来看下如果我们要查所有数据的金额总和怎么办呢,这时候我们就要提到SQL中自带的SUM函数了,所以我们要怎么做呢?
public int getAllMoney() {
SQLiteDatabase database = getWritableDatabase();//获得数据库对象
Cursor cursor = database.query(TABLE, new String[]{"SUM(cost_money)"}, null, null, null, null, null);
int money = 0;
if(cursor!=null){
cursor.moveToNext();
money = cursor.getInt(cursor.getColumnIndex("SUM(cost_money)"));
}
return money;
}
我们把需要查询的列名中传入字符串SUM(cost_money),这样就相当于在SQL语句的select中输入SUM(cost_money)一样。这样我们就得到了一个Cursor数据,但是我在这里犯了一个巨大的错误,我一开始忘记cursor.moveToNext(),所有程序直接崩溃了。
然后我们如果要分别把支出和收入求出来怎么办呢,这时候我们就需要判断一下,cost_money的值是大于0的还是小于0的,然后再求和,代码如下:
public int getIncome(){
SQLiteDatabase database = getWritableDatabase();//获得数据库对象
Cursor cursor = database.query(TABLE, new String[]{"SUM(cost_money)"}, "cost_money>?", new String[]{"0"}, null, null, null);
int money = 0;
if(cursor != null){
cursor.moveToNext();
money = cursor.getInt(cursor.getColumnIndex("SUM(cost_money)"));
}
return money;
}
public int getExpenditure(){
SQLiteDatabase database = getWritableDatabase();//获得数据库对象
Cursor cursor = database.query(TABLE, new String[]{"SUM(cost_money)"}, "cost_money<?", new String[]{"0"}, null, null, null);
int money = 0;
if(cursor != null){
cursor.moveToNext();
money = cursor.getInt(cursor.getColumnIndex("SUM(cost_money)"));
}
return money;
}
这时候我们就用到了条件子句的参数了,我们要判断的是cost_money的值,所有我们selection传入字符串”cost_money > ?”或”cost_money < ?”,selectionArgs 传入字符串集new String[]{“0”},这样我们就能查出我们所需要的值了。
更新数据
当然我们也有可能会把数据写错,所以我们要对于数据进行更新,我们来看下update方法所需要的参数
public int update(String table, ContentValues values, String whereClause, String[] whereArgs);
- String table 传入要插入的表名
- ContentValues values 需要更新的数据
- String whereClause 满足该whereClause子句的记录将会被删除
- String[] whereArgs 用于为whereArgs子句传入参数
在我的记账本中如果发现有一次的记录打错了怎么办呢,那我们就需要更改这条记录了,所以我们在帮助类中新建了一个方法用于更新数据,同样我们传入一个CostBean对象,然后我们要在方法中新建一个ContentValues对象,然后我们想这个ContentValues中传入我们需要修改的值,然后我们调用SQLiteDatabase的update方法把对象传入进行,怎么查找这条数据呢,就是和删除一样的了。
public int upDate(CostBean costBean){//更新数据
SQLiteDatabase database = getWritableDatabase();//获得数据库对象
ContentValues contentValues = new ContentValues();
contentValues.put(COST_TITLE, costBean.costTitle);
contentValues.put(COST_DATE, costBean.costDate);
contentValues.put(COST_MONEY, costBean.costMoney);
int num = database.update(TABLE,contentValues,"id like ?", new String[]{"" + costBean.id});
return num;
}
其实这个把插入和删除搞懂了就很容易理解了。
这个项目的GitHub地址:传送门