SQLite数据库是安卓系统内置的,它是一款轻量级的关系数据库,它运算速度特别快,占用资源很少,通常只需要几百kb的内存就足够,特别适合在移动设备上使用。它不仅支持标准的SQL语法,还遵循数据库的ACID事务。而且SQLite又比一般的数据库要简单得多,甚至不用设置设置用户和密码就可以使用。因此,我们就开始学习这轻量级的SQLite数据库把!
1)创建数据库
Android提供一个SQLiteOpenHelper帮助类,借助这个类就可以非常简单的对数据库进行创建和升级。下面就对SQLiteOpenHelper的基本用法进行介绍:
首先要知道SQLiteOpenHelper是一个抽象类,需要使用它我们就应该创建一个自己的帮助类去继承它。SQLiteOpenHelper中有两个抽象方法,分别是onCreate()和onUpgrade().我们必须在自己的帮助类里面重写这两个方法,然后分别在这两个方法中实现创建、升级数据库的逻辑。
SQLiteOpenHelper中还有两个非常重要的实例方法:getReadeableDatabase()和getWritableDatabase().这两个方法都可以创建或者打开一个现有的数据库(如果数据库已经存在这直接打开,否则直接创建一个数据库),并返回一个可以对数据库进行读写操作的对象。不同的是,当数据库不可写入的时间(磁盘空间已满),getReadableDatabase()方法返回的对象将以只读的方式去打开数据库,而getWritableDatabase()方法则将出现异常。
SQLiteOpenHelper两个构造方法可供重写,一般使用参数少一点的那个构造方法即可。这个构造方法中接收4个参数,第一个参数是Context,,必须有它才能对数据库进行操作,第二个参数是数据库名,创建数据库时使用的就是这里制定的名称。第三个参数允许我们在查询数据的时候返回一个自定义的Cursor,一般传入null。第四个参数表示在调用它getReadableDatabase()或者getWritableDatabase()方法就能够创建数据库了,数据库文件会存放在/data/data/<package name>/database/目录下。此时,重写的onCreate()方法也会得到执行,所以通常会再这里去处理一些创建表的逻辑。
说了这么多,我们还是来做一个例子吧!新建一个DatabaseTest项目,我们创建一个名为BookStore.db的数据库,然后在这个数据库中新建一张Book和Category表,表中有id(主键)、作者、价格、页数、书名等列。创建数据库需要用建表语句的,这里需要SQL的基本知识。Book表的建表语句如下所示
create table Book (
id integer primary key autoincrement,
author text,
price real,
pages integer,
name text)
create table Category(
id integer primary key autoincrement,
category_name text,
category_code integer
);
分析:上面的代码新建了两个表表中包含整形(integer)的id 作为主键,author是文本类型(text),price是浮点型(real),pages是整形,name是文本类型。
然后需要代码执行这条SQL语句,才能完成表的操作。新建MyDatabaseHelper类继承至SQLiteOpenHelper,代码如下所示:
public class MyDatabaseHelper extends SQLiteOpenHelper {
public static final String CREATE_BOOK = "create table Book(" +
" id integer primary key autoincrement, " +
"author text,"+
"price real,"+
"pages integer," +
"name text)";
public static final String CREATE_CATEGORY = "create table Category(" +
" id integer primary key autoincrement," +
" category_name text," +
" category_code integer" +
")";
private Context mContext;
public MyDatabaseHelper(Context context , String name,SQLiteDatabase.CursorFactory factory,int vertion){
super(context,name,factory,vertion);
mContext = context;
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_BOOK);
db.execSQL(CREATE_CATEGORY);
Toast.makeText(mContext, "Create succeeded", Toast.LENGTH_SHORT).show();
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("drop table if exists Book");
db.execSQL("drop table if exists Category");
onCreate(db);
}
}
代码分析:我们把建表的语句定义成了一个字符串常量,在onCreate方法中又调用了SQLiteDatabase的execSQL()方法去执行这两条建表语句,并弹出一个Toast提示创建成功!,这样就可以保证在数据库创建完成的同时还能成功创建Book表。这样是可以实现的,但是当我创建成功之后,如果我又想在BookStore.db文件里创建表的话因为此时BookStore.db文件已经存在所以不管我们怎么点击create database按钮,MyDatabaseHelper中的onCreate()方法都不会在执行,因此新添加的表也就无法创建。因此解决问题的方法有两个,推荐第二个
第一个:通过卸载程序,然后重新运行,这时候BookStore.db这个文件不存在了,在点击create database 按钮
第二个:运用SQLiteHelper的升级功能实现表的添加
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("drop table if exists Book");
db.execSQL("drop table if exists Category");
onCreate(db);
}
在onUpgrade()方法里执行了两条DROP语句,如果发现数据库已经存在Book或者Category表,就将这两张表删除,在调用onCreate()方法重新创建。这里先将已存在的表删除掉,因为如果创建表时发现这张表已经存在就会直接报错。
但是又有一个问题来了。如何让onUpgrade()方法2执行?还记得SQLiteOpenHelper构造方法里接受的四个参数吗?第四个参数是版本号,上面我传的是1,如果要更新表那么只要传入一个比1大的数,就可以让onUpgrade()方法得到执行。如下所示
dbHelper = new MyDatabaseHelper(this,"BookStore.db",null,2);//第四个传入的参数(版本号)改成2就可以了(详见下面MainActivity代码)
接着修改activity_main.xml文件的代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/create_database"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Create database" />
</LinearLayout>
在布局中加入一个按钮,用于创建数据库。
最后修改MainActivity的代码
public class MainActivity extends AppCompatActivity {
private MyDatabaseHelper dbHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dbHelper = new MyDatabaseHelper(this,"BookStore.db",null,1);
Button createDatabase = (Button) findViewById(R.id.create_database);
createDatabase.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dbHelper.getWritableDatabase();
}
});
}
}
代码分析:通过onCreate方法构建了一个MyDatabaseHelper对象,并且通过构造函数的参数建数据库指明为BookStorte,版本号为1,然后在Create database按钮点击事件中调用getWritableDatabase()方法,当第一次点击按钮的时候,就会监测到单号给钱程序没有BookStore.db这个数据库,于是创建该数据库,并调用MyDatabaseHelper中的onCreate()方法,这样Book和Catagory表也就得到了创建,然后会弹出一个Toast提示创建成功.
2)添加数据
从1)中已经掌握了创建和升级数据库的方法,接下来就学习如何对表中的数据进行操作:
四种数据操作:CRUD(创建(create)、查询(retrieve)、更新(update)、删除(delete)),每一个操作对应一个SQL命令
安卓提供了一系列数据操作的辅助性方法,即使不编写SQL语句,也可以轻松完成CRUD操作;
调用SQLiteOpenHelper的getReadableDatabase()或getWritableDatabase()方法是可以用于创建和升级数据库的。两个方法还都会返回一个SQLiteDatabase对象,借助这个对象就可以对数据进行CRUD操作。
说那么多开始学习CRUD四种数据操作吧:
添加数据:SQLiteDatabase提供一个insert()方法,这个方法专门用来添加数据。它接收3个参数:(第一个表名,第二个“在未制定添加数据的情况下给某些可为空的列自动赋值NULL,”一般传入null,第三个ContentValues对象”put()方法重载,用于向ContentValues中添加数据”)。
2.1)实现添加数据的功能
修改activity_main.xml代码, 功能:添加一个添加数据的按钮
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
............................................
<Button
android:id="@+id/add_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Add data"/>
</LinearLayout>
修改MainActivity代码 功能:获取添加按钮,并实现添加数据的功能
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dbHelper = new MyDatabaseHelper(this,"BookStore.db",null,2);
Button createDatabase = (Button) findViewById(R.id.create_database);
createDatabase.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dbHelper.getWritableDatabase();
}
});
Button addData = (Button) findViewById(R.id.add_data);
addData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
//开始组装第一条数据
values.put("name","Android");
values.put("author","Android");
values.put("pages",10000);
values.put("price",50);
db.insert("Book",null,values);//插入第一条数据
values.clear();
//开始组装第二条数据
values.put("name","java web");
values.put("author","java");
values.put("pages",200);
values.put("price",20);
db.insert("Book",null,values);//插入第一条数据
}
});
}
2.2)更新数据
刚刚学习了添加数据,现在我们来学习修改表中的已有数据。继续使用上面的代码,首先修改activity _main.xml文件中的代码: 功能:添加更新数据按钮控件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
....................................
<Button
android:id="@+id/update_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Update data"/>
</LinearLayout>
修改MainActivity的代码 功能 : 指定一组数据,把价格这一列数据更新成10.55
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dbHelper = new MyDatabaseHelper(this,"BookStore.db",null,2);
....................
Button updateData = (Button) findViewById(R .id.update_data);
updateData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
//构建ContentValues对象,并且给它指定了一组数据
ContentValues values = new ContentValues();
values.put("price",10.55);//将价格改成 10.55
db.update("Book",values,"name = ?",new String[] {"Android"});//SQL语句 找到 name=”Android”的一行数据进行更新
}
});
}
2.3)删除数据
删除数据,跟上述类似,SQLiteDatabase 中提供一个delete()方法,专门用于删除数据,这个方法接收3个参数,第一个参数是表明,第二第三个参数又是用于约束删除某一行或几行的数据,不指定的话就是默认删除所有行。
下面进行实践练习,仍然使用上述的代码,首先修改activity_main.xml的代码 功能一样添加一个删除按钮
<Button
android:id="@+id/delete_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Delete data"/>
然后修改MainActivity中的代码 功能 : 删除页面(pages)大于190的数据
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dbHelper = new MyDatabaseHelper(this,"BookStore.db",null,2);
....................................(中间代码省略)
Button deleteButton = (Button) findViewById(R.id.delete_data);
deleteButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
db.delete("Book","pages > ?",new String[] {"190"});//删除Book表中页数(pages)大于190
}
});
}
2.4)查询数据
查询数据之前应该要注意一点,它是最复杂的一种操作。SQL大部分功能都体现在查询方面。安卓提供的方法SQLiteDatabase中提供了一个query()方法用于对数据进行查询,这个方法比较复杂,要传入7个参数。
第一个参数:表名 第二个参数:去查询哪几列,不指定默认查询所有列 第三、四个参数:查询某一行或者某几行数据,不指定则默认查询所有列 第五个参数:指定需要去group by的列,不指定则表示不对查询结果进行 group by操作
第六个参数:对group by之后的数据进行进一步的过滤,不指定表示不进行过滤 第七个参数:用于指定查询结果的排序方式,不指定则表示使用默认排序方式。更多详细参数参考下
虽然query()方法传入的参数多,但是不要对它产生畏惧,因为我们不必为每一条查询语句都指定所有的参数,多数情况都是传入少数几个参数就可以完成查询操作。调用query()方法后会返回一个Cursor对象,查询到的所有的数据都将从这个对象取出。
说这么多还是用实际的例子来体验一下query()方法吧!还是继续使用2.2)的代码
首先修改activity_main.xml中的代码 功能:添加查询指令的按钮
<Button
android:id="@+id/query_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Query data"/>
然后修改MainActivity里面的代码 功能:实现数据查询query()操作
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dbHelper = new MyDatabaseHelper(this,"BookStore.db",null,2);
Button createDatabase = (Button) findViewById(R.id.create_database);
.........................................(中间内容省略)
Button queryButton = (Button) findViewById(R.id.query_data);
queryButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SQLiteDatabase db = dbHelper.getWritableDatabase();//调用SQLiteDatabase的query()方法去查询数据。
//查询表中所有数据 这里只是使用了第一个参数查询Book表
Cursor cursor = db.query("Book",null,null,null,null,null,null);//得到cursor对象,
if (cursor.moveToFirst()){//调用它的moveToFirst()方法将数据的指针移动到第一行的位置,然后进入一个循环当中
do {
//遍历Cursor对象,取出数据并打印 遍历查询每一行数据
String name = cursor.getString(cursor.getColumnIndex("name"));
//通过Cursor的getColumnIndex()方法获取到某一列在表中对应的位置索引,然后将这个索引传入到相应的取值方法中,就可以得到从数据库中读取到的数据了
String author = cursor.getString(cursor.getColumnIndex("author"));
int pages = cursor.getInt(cursor.getColumnIndex("pages"));
double price = cursor.getDouble(cursor.getColumnIndex("price"));
Log.d("MainActivity","book name is"+name);//
Log.d("MainActivity","book author is"+author);
Log.d("MainActivity","book pages is"+pages);
Log.d("MainActivity","book price is"+price);
}while(cursor.moveToNext());
}
cursor.close();//最后调用close()方法关闭Cursor
}
});
}
2.5)SQL操作数据库
2.5.1)添加数据的方法
db.execSQL(
"insert into Book(name,author,pages,price) values(?,?,?,?)", new String[]{"android","Tony","380","27 j"}"
);
db.execSQL(
"insert into Book(name,author,pages,price) values(?,?,?,?)", new String[]{"The Android 1","ToMas","359","57"}
);
\
2.5.2)更新数据方法
db.execSQL(
"update Book set price = ? where name = ?",new String[]{"345","Android"}
);
2.5.3)删除数据
db.execSQL(
"delete from Book where pages > ?",new String[]{"500"}
);
2.5.4)查询数据
db.rawQuery(
"select * from Book",null
);
2.6)学会使用adb调试(以数据库查询为例)
简介:adb是Android SDK自带的一个调试工具,使用这个工具可以直接对连接在电脑上的手机或者模拟器进行调试操作。它存放在sdk的platform-tools目录。
使用方法:1、Windows平台,右击计算机属性->高级属性设置->环境变量,然后在环境变量里找到Path并点击编辑,将platform-tools目录配置进去就可以使用了。
2、Linux或者是Mac系统,可以在home路径下编辑.bash_文件,将platform-tools目录配置进去即可,配置好之后就可以使用了。
配置好之后,进入到设备的控制台(cmd)使用adb shell命令进入到安卓目录 然后使用cd命令进入到/data/data/com.example.a14468.databasetest/databases/目录下,并使用ls命令查到当前目录里的文件。
这个目录会出现两个数据库文件,一个是自行创建的.db文件,另一个是.db-journal(为了让数据库能够支持事务而产生的临时日志文件)
通过借助sqlite命令来打开数据库 格式 : sqlite3 文件名.db
常用的指令:.table(擦汗寻遍数据库中有哪些表)、.schema(查看建表语句)、.exit/.quit(退出设备控制台)