使用 SQLite 本地数据库

为存储数据到数据库,首先需要定义数据库结构并打开数据库。 Android 提供了一个帮助类 SQLiteOpenHelper ,其中封装了一些存储应用数据的常用数据库操作,如 创建打开 以及 更新数据库 等。

SQLiteOpenHelper 类的常用方法

构造方法

SQLiteOpenHelper (Context context, //用来打开或创建一个数据库
                String name, //用来指定数据库文件,若为 null 则指内存中的数据库
                SQLiteDatabase.CursorFactory factory, //用来创建游标 Cursor 对象,若为 null 则使用默认的
                int version) //数据库版本号,应为从 1 开始的递增整数值。

Tips: 关于版本号:
SQLiteOpenHelper 类有着管理不同版本数据库结构的能力。如果应用当前数据库版本更老,会通过 onUpgrade(SQLiteDatabase, int, int) 来更新数据库版本;反之如果当前应用数据库版本更新,则会通过 onDowngrade(SQLiteDatabase, int, int) 对数据库版本进行降级。
因此在实际应用中,每次对数据库结构做出调整后,都应该增加版本号常量。

公开的成员方法

//关闭任何已打开的数据库对象
void close () 

//创建或打开数据库
SQLiteDatabase getReadableDatabase () 

//创建或打开一个可读、可写的数据库
SQLiteDatabase getWritableDatabase () 

//配置数据库连接
void onConfigure (SQLiteDatabase db) 

//第一次创建数据库时调用。数据库表的创建以及表的初始内容的填充 在这里完成。
void onCreate (SQLiteDatabase db) 

//数据库降级
void onDowngrade (SQLiteDatabase db, 
                int oldVersion, 
                int newVersion) 
                
//数据库升级
void onUpgrade (SQLiteDatabase db, 
                int oldVersion, 
                int newVersion) 

Tips:
一般情况下,getReadableDatabase ()getWritableDatabase () 方法返回的是同一个对象,但如果出现一些极端情况(如硬盘满了),那么调用 getReadableDatabase () 方法返回的就是一个只读的数据库。

这两种方法都会花费较长的时间,因此官方不建议从主线程(包括 ContentProvider.onCreate() )中调用。

SQLiteDatabase 类常用方法

执行 SQL 语句

/**
 * execSQL()
 * 作用: 执行一个非 SELECT 的 SQL 语句或任何其他返回数据的 SQL 语句
 * @param String: 要执行的SQL语句。不支持以分号分隔的多个语句
 * Throws SQLException: 当传入的 String 无效时
 */
void execSQL(String sql)

官方鼓励开发人员尽可能使用 SQLiteDatabase 内嵌的 insert()update() 方法来取代传统的 SQL 语句,但是博主 Carson_Ho 在相关文章中却建议多使用 SQL 语句(因为相对官方提供的方法更为简单、通用)。至于具体实际应用中使用哪种为多,我也不知道了。。这里就先挖个坑吧,等经验多了再回过头来补充我自己的观点。

插入

/**
 * insert() 
 * 作用: 向数据库中插入一行数据
 * 返回值: long 型。返回新插入的行数,如果插入过程出错则返回 -1
 * @param table: 指定表的名称
 * @param nullColumHack: 可选的; 可能是null。SQL不允许在不命名至少一个列名的
 情况下插入空行。如果您提供的values是空的,则不知道列名称,并且无法插入空行。如
 果未设置为 null ,则该 nullColumnHack 参数提供可为空的列名称的名称,以便在您
 values 为空时显式插入 null
 * @param values: ContentValues - 此映射包含行的初始列值。键应该是列名,值应该是列值
 */
long insert (String table, 
                String nullColumnHack, 
                ContentValues values)             
                
//下面语句的意思是:向名为 SQLTest 的表中插入 id = 1, name = "张三" 的记录
ContentValues value = new ContentValues();
value.put("id", 1);
value.put("name", "张三");
mDatabase.insert("SQLTest", null, value);

删除

/**
 * delete()
 * 作用: 删除数据库中的行
 * 返回值: int 型。如果传入的是 where 子句那么返回受到影响的行数,否则返回 0 。要
 删除所有行并获取总数则传入 1 作为 where 子句
 * @param table: 指定表的名称
 * @param whereClause: 删除时要应用的可选 where 子句。传递null将删除所有行
 * @param whereArgs: 如果在 where 子句中包含 ? ,它将被 whereArgs 中的值替换。
 这些值将会被绑定成为字符串类型
 */
int delete (String table, 
                String whereClause, 
                String[] whereArgs) 
                
//下面语句的意思是:从名为 SQLTest 的表中删除属性 id 值为 1 的行
mDatabase.delete("SQLTest", "id=?", new String[]{"1"});

修改

/**
 * update() 
 * 作用: 更新数据库中的行
 * 返回值: int 型。返回受影响的行数
 * @param table: 指定表的名称
  values 为空时显式插入 null
 * @param values: ContentValues - 此映射包含行的初始列值。键应该是列名,值应该是列值
 * @param whereClause: 删除时要应用的可选 where 子句。传递null将删除所有行
 * @param whereArgs: 如果在 where 子句中包含 ? ,它将被 whereArgs 中的值替换。
 这些值将会被绑定成为字符串类型
 */
int update (String table, 
                ContentValues values, 
                String whereClause, 
                String[] whereArgs)

//下面语句的意思是将名为 SQLTest 的表中, id=1 的元组的 name 值改为 "李四"
ContentValues value = new ContentValues();
value.put("name", "李四");
mDatabase.update("SQLTest", value1, "id=?", new String[]{"1"});

查询

/**
 * query()
 * 作用: 查询给定的 URL,返回 Cursor 结果集
 * 返回值: 一个 Cursor 对象
 * @param distinct: 消除相同行
 * @param table: 指定表的名称
 * @param columns: 要返回的列的列表(不建议为 null ,防止直接从内存中读取数据)
 * @param selection: 一个过滤器,声明要返回哪些行,格式化为 SQL WHERE 子句(不包
 括 WHERE 本身)。传入 null 将返回给定表的所有行
 * @param selectionArgs: 如果在 selection 中包含了 ? ,那么它将被 selectionArgs 中的值替换
 * @param groupBy: 一个过滤器,声明如何对行进行分组,格式化为 SQL GROUP BY 子句(不包
 括 GROUP BY 本身)。传入 null 将导致行不被分组。
 * @param having: 一个过滤器,声明要在游标中包含哪些行组,如果正在使用行分组,则格式化为
 SQL HAVING 子句(不包括 HAVING 本身)。传入 null 将导致包含所有行组,并且在未使用行分
 组时是必需的
 * @param orderBy: 如何对行进行排序,格式化为 SQL ORDER BY 子句(不包括 ORDER BY 本身)。
 传入 null 将使用默认排序顺序,该顺序可能是无序的
 * @param limit: 限制查询返回的行数,格式为 LIMIT 子句。传入 null 表示没有 LIMIT 子句
 */
Cursor query (boolean distinct, 
                String table, 
                String[] columns, 
                String selection, 
                String[] selectionArgs, 
                String groupBy, 
                String having, 
                String orderBy, 
                String limit)

//query() 还有其他类似结构的方法,由于是部分参数的变化,这里就不一一列出了

由于这里涉及到了 Cursor ,因此要对查询结果进行进一步的操作就需要利用 Cursor 给出的方法,这里直接列出常用方法不再做多的说明:

//下面语句的意思是:将名为 SQLTest 的表中 id=1 的 "id" 列和 "name" 列返回给游标 Cursor
Cursor c = mDatabase.query(null, "SQLTest", 
                new String[]{"id", "name"}, 
                "id=?", 
                new String[]{"1"}, 
                null, null, null);

    c.move(int offset); //以当前位置为参考,移动到指定行  
    c.moveToFirst(); //移动到第一行  
    c.moveToLast(); //移动到最后一行  
    c.moveToPosition(int position); //移动到指定行  
    c.moveToPrevious(); //移动到前一行  
    c.moveToNext(); //移动到下一行  
    c.isFirst(); //是否指向第一条  
    c.isLast(); //是否指向最后一条  
    c.isBeforeFirst(); //是否指向第一条之前  
    c.isAfterLast(); //是否指向最后一条之后  
    c.isNull(int columnIndex); //指定列是否为空(列基数为0)  
    c.isClosed(); //游标是否已关闭  
    c.getCount(); //总数据项数  
    c.getPosition(); //返回当前游标所指向的行数  
    c.getColumnIndex(String columnName); //返回某列名对应的列索引值  
    c.getString(int columnIndex); //返回当前行指定列的值

Demo

使用 SQLite 本地数据库_第1张图片
SQLTest Demo

本来想着把 Demo 放到 github 上的,但是由于代码实现起来较为容易,也没有这个必要,这里就不再放出了。

参考资源:

Android API
Android 编程权威指南 [美]Phillips,B. [美]Hardy,B. [译]王明发 (人民邮电出版社)
Android :SQLlite数据库 使用手册 -- Carson_Ho

你可能感兴趣的:(使用 SQLite 本地数据库)