SQLiteOpenHelper与SQLiteDatabase的使用
1. 数据类型
与其它数据库不同,SQLite的数据类型很简单,只有NULL(空类型)、INTEGER(整型)、REAL(浮点型)、TEXT(字符串型)、BLOB(二进制型)。
SQLite为动态数据类型(弱引用),当向数据库中插入某个值时,会检查该值的类型,若类型与插入列不匹配,SQLite会尝试将该值转换成相应类型。
2. 创建数据库
如果对SQL的操作不了解,建议先看看这一块:MySQL入门笔记(一)
Android中提供了一个SQLiteOpenHelper类,使用该类可非常方便地进行数据库的创建与升级。
SQLiteOpenHelper是一个抽象类,必须实现onCreate()、onUpgrade(),这两个方法分别用于数据库的创建与升级,onCreate()在数据库不存在的情况下会调用,而onUpgrade()则是当版本号高于已有数据库时调用。
SQLiteOpenHelper构造函数的第一个参数是context,第二个参数是数据库的名称,第三个参数允许在查询数据时返回一个自定义的Cursor,直接传入null即可,第四个参数是数据库版本号,用于数据库的升级操作。
调用getReadableDtabase()或者getWritableDatabase()方法即可创建或打开数据库,同时返回一个SQLiteDatabase对象,用于操作数据库。这里,SQLiteDatabase对象有两个重要方法,exexSQL方法和rawQuery方法,前者用于执行SQL语句,后者用于查询记录,后面会具体介绍。
拓展:Context与SQLiteDatabase的方法openOrCreateDatabase的区别 (context、SQLiteOpenHelper)
范例:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new SQLiteOpenHelper(this, "Library.db", null, 1) {
static final String CREATE_BOOK = "create table BOOK ("
+ "id integer primary key autoincrement, "
+ "name text, "
+ "author text)";
@Override
public void onCreate(SQLiteDatabase db) {
// 创建数据表
db.execSQL(CREATE_BOOK);
Toast.makeText(MainActivity.this, "创建成功!", Toast.LENGTH_SHORT).show();
}
// 用于升级数据库
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}.getWritableDatabase();
}
}
3. 升级数据库
在进行app的迭代时,往往也会伴随着进行数据库的升级,这就需要通过onUpgrade()方法实现。需要升级数据库时,在实例化SQLiteOpenHelper时传入一个更高的版本号即可。
范例:
假定进行两次迭代:1. 新增一张表catelogy,2. 给表book增加category_id字段。
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new SQLiteOpenHelper(this, "Library.db", null, 1) {
static final String CREATE_BOOK = "create table BOOK ("
+ "id integer primary key autoincrement, "
+ "name text, "
+ "author text,"
+ "category_id integer)";//第二次升级时增加
static final String CREATE_CATEGORY = "create table CATEGORY ("
+ "id integer primary key autoincrement, "
+ "category_name text,"
+ "category_code integer)";
static final String CHANGE_COLUMN = "alter table BOOK column category_id integer";
@Override
public void onCreate(SQLiteDatabase db) {
// 如果用户当前是初次安装本程序,即数据库未被创建,则直接创建两个表
db.execSQL(CREATE_BOOK);
db.execSQL(CREATE_CATEGORY);
Toast.makeText(MainActivity.this, "创建成功!", Toast.LENGTH_SHORT).show();
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
switch (oldVersion) {
// 不使用break
case 1:
db.execSQL(CREATE_CATEGORY);
case 2:
db.execSQL(CHANGE_COLUMN);
default:
}
}
}.getWritableDatabase();
}
}
这里注意一个细节,onUpgrade()方法中的switch语句里的并未使用break,这是为了保证在跨版本升级时能顺利依次完成中间的所有升级。
4. 数据操作
4.1 execSQL()和rawQuery()
上面提到,调用getReadableDatabase()或者getWritableDatabase()方法时会返回一个SQLiteDatabase对象,要对数据进行操作,就是使用这一对象。
结合上面的例子,我们可以看到SQLiteDatabase提供了一个调用SQL语句的方法execSQL(),通过这个方法可以调用除查询语句以外的SQL语句,同时SQLiteDatabase类提供了一个rawQuery()方法,用于查询数据。
(1)execSQL()
execSQL(String sql)
execSQL(String sql, Object[] bingArgs)
使用execSQL()方法传入参数有两种方式,第一种直接传入SQL语句,如有参数则直接拼接在一起,例如:
String delete_sql = "delete from test where _id = " + idString;
db.execSQL(sql);
第二种方法则是在参数的位置插入占位符?,而后将具体参数传给execSQL()方法的第二个参数,如有多个参数,则依次放入:
String delete_sql = "delete from test where _id = ?, name = ?";
db.execSQL(sql, new String[] {idString, nameString});
(2)rawQuery()
rawQuery(String sql, String[] selectionArgs)
rawQuery()方法的使用与execSQL()的第二种用法基本一致。
4.2 安卓提供的API
除了execSQL()方法和rawQuery()方法,安卓还针对数据库的CRUD操作封装了API,更加便于操作。
(1)insert()
insert(String table, String nullColumnHack, ContentValues values)
table
:表名。
nullColumnHack
:若某些允许为空的列没有赋值,则自动赋值为null,传入null即可。
values
:ContentValues对象,相当于一个容器的作用,可通过它的put(key, values)方法(key为列名称,values为该列的值)将每一行的数据一一添加,而后再传入数据库。如需插入多条记录,插入下一条记录前要调用clear()方法进行清空。
返回一个id值,即插入记录的id。
范例:
//获取SQLiteDatabase对象
db = mHelper.getWritableDatabase();
//实例化ContentValues对象并进行数据组装
ContentValues values = new ContentValues();
values.put("name", "A");
values.put("author", "aa");
//插入数据
db.insert("BOOK", null, values);
//若需要插入多条记录,在这一步一定要调用values的clear()方法清空现有的数据
values.clear();
values.put("name", "B");
values.put("author", "bb");
db.insert("BOOK", null, values);
(2)delete()
delete(String table, String whereClause, String[] whereArgs)
whereClause
和whereArgs
:指定删除条件,若不指定则删除表中所有数据。即SQL中where字句部分,占位符的使用同execSQL()与rawQuery(),例如将age > 30的记录删除,则第二个参数为"age > ?",第三个参数为new String[] {"30"}。
范例:
//删除数据,?是一个占位符,第二、第三个参数合起来即删除id > 2的记录
db.delete("BOOK", "id > ?", new String[] {"2"});
(3)update()
update(String table, ContentValues values, String whereClause, String[] whereArgs)
values同Insert()方法,将更新后的数据通过ContentValues对象组装,而whereClause和whereArgs则同delete()方法,指定更新哪些记录。
范例:
ContentValues values = new ContentValues();
values.put("name", "D");
db.update("BOOK", values, "id < ?", new String[] {"3"});
(4)query()
query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy)
如果学过SQL语言的话,相信对上面这一长串的参数是比较容易理解的,基本上可以与SQL中select语句的结构对应上。调用query()方法会返回一个Cursor对象,里面含有所有查询结果。
table
:对应SQL中的from table_name
,指定查询的表名。
columns
:对应select column1, column2, ...
,指定查询的列名称。
selection
:对应where column = value
,指定查询的行的约束条件。
selectionArgs
:为selection中的占位符(?)提供具体值。
groupBy
:对应group by column
,指定对哪一列进行分组。
having
:对应having column = value
,进一步对分组后的结果进行约束。
orderBy
:对应order by column1, column2, ...
,指定查询结果的排序方式。
范例:
db = mHelper.getWritableDatabase();
//查询BOOK中所有数据
Cursor cursor = db.query("BOOK", null, null, null, null, null, null);
if (cursor.moveToFirst()) {
do {
//遍历cursor,取出数据
int id = cursor.getInt(cursor.getColumnIndex("id"));
String name = cursor.getString(cursor.getColumnIndex("name"));
String author = cursor.getString(cursor.getColumnIndex("author"));
//打印数据
Log.d("MySQLiteData", id + ". 《" + name + "》 " + author);
}while (cursor.moveToNext());
//关闭Cursor对象
cursor.close();
}
5. 事务
SQLite是支持事务的,那么什么是事务呢?假定需要更新大量数据,就要先删除旧数据,而后再插入新数据。但是在过程中出现了异常,旧数据被删除之后,新数据没有成功插入,那这一个数据表的信息就全没了。
事务的特性就是保证某一个系列的操作,或者全部完成,或者全部不完成。如果替换数据放在事务中进行,则要么数据替换成功,表内全部换成新数据,要么失败,保留旧数据,不会出现删了旧数据,但是没插入新数据的情况。
事务的使用方法非常简单:
// 通过SQLiteDatabase对象开启事务
db.beginTransaction();
try {
// 在异常捕获的代码块中进行具体的操作
// 在全部操作结束后将事务设置为成功
db.setTransactionSuccessful();
} catch (Exception e) {
e.printStackTrace();
} finally (
// 结束事务
db.endTransaction();
)
SQLiteOpenHelper与SQLiteDatabase的使用的更多相关文章
- SQLiteOpenHelper/SQLiteDatabase/Cursor源代码解析
转载请注明出处:http://blog.csdn.net/y_zhiwen/article/details/51583188 Github地址.欢迎star和follow 新增android sqli ...
- 关于android的SQLiteDatabase和Cursor的一些疑问
android数据库操作的基础有三个类:SQLiteOpenHelper,SQLiteDatabase和Cursor.其中,SQLiteOpenHelper会建立一个数据库连接,它虽然可以调用多次ge ...
- Android之SQLite数据库篇
一.SQLite简介 Google为Andriod的较大的数据处理提供了SQLite,他在数据存储.管理.维护等各方面都相当出色,功能也非常的强大. 二.SQLite的特点 1.轻量级使用 SQLit ...
- (转) Android开发性能优化简介
作者:贺小令 随着技术的发展,智能手机硬件配置越来越高,可是它和现在的PC相比,其运算能力,续航能力,存储空间等都还是受到很大的限制,同时用户对手机的体验要求远远高于PC的桌面应用程序.以上理由,足以 ...
- Android数据存储之Sqlite的介绍及使用
前言: 本来没有打算整理有关Sqlite数据库文章的,最近一直在研究ContentProvider的使用,所有觉得还是先对Sqlite进行一个简单的回顾,也方便研究学习ContentProvider. ...
- Android之sqlite的使用 (转载)
Android中的SQLite使用 首先创建数据库类 public class DatabaseHelper extends SQLiteOpenHelper { private stat ...
- Android之数据库的创建
一.SQLite介绍 SQLite 一个非常流行的嵌入式数据库,它支持 SQL 语言,并且只利用很少的内存就有很好的性能.此外它还是开源的,任何人都可以使用它.许多开源项目((Mozilla, PHP ...
- android内存优化
背景 虽然android设备的配置越来越高,但是,由于android系统的机制导致(最主要是app程序的主线程不会真正退出而是在后台常驻内存中) ,这样手机中安装过多的app之后,导致内存被大量占用, ...
- Android数据存储五种方式总结
本文介绍Android平台进行数据存储的五大方式,分别如下: 1 使用SharedPreferences存储数据 2 文件存储数据 3 SQLite数据库存储数据 4 使用Cont ...
随机推荐
- MIT-线性代数笔记(7-11)
第 07 讲 求解 Ax=0 :主变量,特解 矩阵的秩Rank(A):矩阵主元的个数. 找出“主变量”pivotvariables,主列,即主元所在的列,其他列,称为自由列.(自由列表示可以自由或任意 ...
- 理解Java Integer的缓存策略【转】
本文由 ImportNew - 挖坑的张师傅 翻译自 javapapers.欢迎加入翻译小组.转载请见文末要求. 本文将介绍 Java 中 Integer 缓存的相关知识.这是 Java 5 中引入的 ...
- mongodb window安装配置
下载mongodb安装包 1. https://www.mongodb.org/dl/win32/x86_64-2008plus-ssl?_ga=2.233271640.711265466.15193 ...
- Python面向对象篇(2)-继承
在发表本篇随笔的时候,距离上一次发已经有一个多月了,很多朋友私信我为什么不持续更新了,在这里先跟大家说声抱歉.因为年底的工作较为繁重,实在分不出精力,更重要的也是在思考后面进阶的部分要按怎样的顺序写, ...
- Javascript获取数组中最大和最小值
取出数组中最大值或最小值是开发中常见的需求,今天继续讲解如何获取javascript数组中最大和最小值. 1.排序法 首先我们给数组进行排序,可以按照从小到大的顺序来排,排序之后的数组中第一个和最后一 ...
- 注册表命令 regedit32
转自 https://zhidao.baidu.com/question/1958216489744783460.html Regedt32.exe 不支持注册表项文件 (.reg) 的导入和导出. ...
- idea 打开自动编译以及查看Problem窗口
1.打开perference 2.选择Build-Compile-Make Project Automatically自动构建项目
- HttpClient读取数据乱码的解决方案
博主是一个近十年的老书虫了,从高中那会儿就开始看网络小说.每天半天看晚上看啊,终于眼睛也近视了,成绩也下降了(....好像说远了) 最近在追辰东的<圣墟>,最近写到精彩部分了,一直等更新. ...
- 遇见JMS[1] —— activeMQ的简单使用
1.JMS Java Message Service,提供API,供两个应用程序或者分布式应用之间异步通信,以传送消息. 2.相关概念 提供者:实现JMS规范的消息中间件服务器客户端:发送或接收消息的 ...
- html5版 音乐播放器
html5版本音乐播放器,支持iOS设备,案例地址:http://www.xttblog.com/?p=1277 功能说明 支持iOS设备,但是iOS不支持自动下一曲,这是iOS本身限制,支持touc ...