美文网首页
使用 SQLite 本地数据库

使用 SQLite 本地数据库

作者: ImAoJin | 来源:发表于2018-10-15 21:53 被阅读0次

    为存储数据到数据库,首先需要定义数据库结构并打开数据库。 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

    SQLTest Demo

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

    参考资源:

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

    相关文章

      网友评论

          本文标题:使用 SQLite 本地数据库

          本文链接:https://www.haomeiwen.com/subject/wwbqzftx.html