Android提供了5种方式来让用户保存持久化应用程序数据。根据自己的需求来做选择,比如数据是否是应用程序私有的,是否能被其他程序访问,需要多少数据存储空间等,分别是: 

①使用SharedPreferences存储数据 

②文件存储数据

        ③SQLite数据库存储数据

④使用ContentProvider存储数据

⑤网络存储数据 

使用SQLite保存数据

对于重复数据或结构化数据(例如联系信息),将数据保存到数据库是理想选择。下面咱咱就开始在Android上使用SQLite数据库。android.database.sqlite软件包中提供了在Android上使用数据库所需的API。

咱先玩玩SQLite数据库,后面咱从SQLite迁移到Room。

注意:虽然这些API功能强大,但它们的级别较低,使用起来需要花费大量时间和精力:

  • 没有针对原始SQL查询的编译时验证。随着数据图表不断发生变化,你需要手动更新受影响的SQL查询。此过程既耗时又容易出错。
  • 你需要使用大量样板代码,在SQL查询和数据对象之间进行转换。

出于这些原因,咱强烈建议将Room持久性库用作抽象层以访问应用的SQLite数据库中的信息。

SQL的基本语法

SQL本质上是一种编程语言,它的学名叫作“结构化查询语言”(全称为StructuredQuery Language,简称SQL)。不过SQL语言并非通用的编程语言,它专用于数据库的访问和处理,更像是一种操作命令,所以常说SQL语句而不说SQL代码。标准的SQL语句分为3类:数据定义、数据操纵和数据控制,但不同的数据库往往有自己的实现。

SQLite是一种小巧的嵌入式数据库,使用方便、开发简单。如同MySQL、Oracle那样,SQLite也采用SQL语句管理数据,由于它属于轻型数据库,不涉及复杂的数据控制操作,因此App开发只用到数据定义和数据操纵两类SQL。此外,SQLite的SQL语法与通用的SQL语法略有不同。

数据库帮助器SQLiteOpenHelper

由于SQLiteDatabase存在局限性,一不小心就会重复打开数据库,处理数据库的升级也不方便;因此Android提供了数据库帮助器SQLiteOpenHelper,帮助开发者合理使用SQLite。

SQLiteOpenHelper的具体使用步骤如下:

        步骤1:新建一个继承自SQLiteOpenHelper的数据库操作类,按提示重写onCreate和onUpgrade两个方法。其中,onCreate方法只在第一次打开数据库时执行,在此可以创建表结构;而onUpgrade方法在数据库版本升高时执行,在此可以根据新旧版本号变更表结构。

        步骤2:为保证数据库安全使用,需要封装几个必要方法,包括获取单例对象.打开数据库连接、关闭数据库连接,说明如下:

  • 获取单例对象:确保在App运行过程中数据库只会打开一次,避免重复打开引起错误。
  • 打开数据库连接:SQLite有锁机制,即读锁和写锁的处理;故而数据库连接也分两种,读连接可调用getReadableDatabase方法获得,写连接可调用getWritableDatabase获得。
  • 关闭数据库连接:数据库操作完毕,调用数据库实例的close方法关闭连接。

        步骤3:提供对表记录增加、删除、修改、查询的操作方法。

继承SQLiteOpenHelper类,重写onCreate、onUpgrade、onOpen方法

public class UserDBHelper extends SQLiteOpenHelper {private static final String DB_NAME = "user.db";//数据库的名称private static UserDBHelper mHelper = null;//数据库帮助器的实例private SQLiteDatabase mDB = null;//数据库的实例public static final String TABLE_NAME = "user_info";public static final String _ID = "_id";public static final String COLUMN_NAME = "name";public static final String COLUMN_AGE = "age";public static final String COLUMN_UPDATE_TIME = "update_time";/*** @param context 上下文环境(例如,一个 Activity)*                DB_NAME  数据库名字*                factory  null  一个可选的游标工厂(通常是 Null)* @param version 数据库模型版本的整数*                会调用父类 SQLiteOpenHelper的构造函数*/public UserDBHelper(Context context, int version) {super(context, DB_NAME, null, version);}//利用单例模式获取SQLiteOpenHelper的唯一实例public static UserDBHelper getInstance(Context context, int version) {if (version > 0 && mHelper == null) {mHelper = new UserDBHelper(context, version);}return mHelper;}//创建数据库表,执行建表语句@Overridepublic void onCreate(SQLiteDatabase db) {}/*** 当数据库需要修改的时候(两个数据库版本不同),Android系统会主动的调用这个方法。* 一般我们在这个方法里边删除数据库表,并建立新的数据库表.*/@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}@Overridepublic void onOpen(SQLiteDatabase db) {//每次成功打开数据库后首先被执行super.onOpen(db);}
}

创建表

表格的创建动作由create命令完成,格式为“CREATE TABLE IFNOT EXISTS表格名称(以逗号分隔的各字段定义);”。以用户信息表为例,它的建表语句如下所示:

//创建数据库表,执行建表语句
@Override
public void onCreate(SQLiteDatabase db) {Log.e(getClass().getName(), "onCreate");//创建表语句String SQL_CREATE_ENTRIES = "CREATE TABLE IF NOT EXISTS "+ TABLE_NAME + "("+ _ID + " INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,"+ COLUMN_NAME+" VARCHAR NOT NULL,"+ COLUMN_AGE+" INTEGER NOT NULL,"+ COLUMN_UPDATE_TIME+" VARCHAR NOT NULL" + "); ";//执行完整的sQL语句db.execSQL(SQL_CREATE_ENTRIES);
}

上面的SQL语法与其他数据库的SQL语法有所出入,相关的注意点说明见下:

①SQL语句不区分大小写,无论是create与table这类关键词,还是表格名称、字段名称,都不区分大小写。唯一区分大小写的是被单引号括起来的字符串值。

②为避免重复建表,应加上IF NOT EXISTS关键词,例如CREATE TABLE IFNOT EXISTS表格名称......

③SQLite支持整型INTEGER、长整型LONG、字符串VARCHAR、浮点数FLOAT,但不支持布尔类型。布尔类型的数据要使用整型保存,如果直接保存布尔数据,在入库时sQLite会自动将它转为0或1,其中0表示false,1表示true。

④建表时需要唯一标识字段,它的字段名为_id。创建新表都要加上该字段定义,例如_id lNTEGER PRIMARY KEY AUTOINCREMENT NOT NULL。

删除表

表格的删除动作由drop命令完成,格式为“DROP TABLE IFEXISTS表格名称;”。下面是删除用户信息表的SQL语句例子:

//删除表
public void deleteTable(SQLiteDatabase db) {String SQL_DELETE_ENTRIES = "DROP TABLE IF EXISTS " + TABLE_NAME;db.execSQL(SQL_DELETE_ENTRIES);
}

打开数据库表

下面这段代码会返回一个 SQLiteDatabase 类的实例,使用这个对象,你就可以查询或者修改数据库。 

//打开数据库的读连接(查询数据库)
public SQLiteDatabase openReadLink() {if (mDB == null || !mDB.isOpen()) {mDB = mHelper.getReadableDatabase();}return mDB;
}//打开数据库的写连接(可写数据库)
public SQLiteDatabase openwriteLink() {if (mDB == null || !mDB.isOpen()) {mDB = mHelper.getWritableDatabase();}return mDB;
}

关闭数据库

//由于在数据库关闭时,调用getWritableDatabase()和getReadableDatabase()的成本比较高,
// 因此只要您有可能需要访问数据库,就应保持数据库连接处于打开状态。通常情况下,
// 最好在发出调用的Activity的onDestroy()中关闭数据库。
@Override
protected void onDestroy() {userDBHelper.closeLink();super.onDestroy();
}

添加数据

使用 SQLiteDatabase 对象的insert()。

//往该表添加多条记录
public long insert(List<UserInfoBean> infoList) {long result = -1;for (int i = 0; i < infoList.size(); i++) {UserInfoBean info = infoList.get(i);//不存在唯一性重复的记录,则插入新记录ContentValues cv = new ContentValues();cv.put(_ID, info.get_id());cv.put(COLUMN_NAME, info.getName());cv.put(COLUMN_AGE, info.getAge());cv.put(COLUMN_UPDATE_TIME, info.getUpdate_time());//执行插入记录动作,该语句返回插入记录的行号result = mDB.insert(TABLE_NAME, "", cv);if (result == -1) {//添加成功则返回行号,添加失败则返回-1return result;}}return result;
}

  方法使用:

List<UserInfoBean> list = new ArrayList<>();
list.add(new UserInfoBean("10", "帅次次", 20, "09:00"));
list.add(new UserInfoBean("12", "朱元璋", 30, "11:00"));
list.add(new UserInfoBean("15", "赵匡胤", 40, "13:00"));
list.add(new UserInfoBean("18", "李世民", 50, "15:00"));
long l = userDBHelper.insert(list);
tv_sql.setText("插入成功:" + l);

修改数据

使用SQLiteDatabase 对象的update()方法。

//根据条件更新指定的表记录
public int update(UserInfoBean info, String condition) {ContentValues cv = new ContentValues();cv.put(COLUMN_NAME, info.getName());cv.put(COLUMN_AGE, info.getAge());cv.put(COLUMN_UPDATE_TIME, info.getUpdate_time());//执行更新记录动作,该语句返回更新的记录数量return mDB.update(TABLE_NAME, cv, condition, null);
}

方法使用:

UserInfoBean bean = new UserInfoBean("武媚娘", 32,"12:00");
userDBHelper.update(bean, "_id=18");

查找数据

使用SQLiteDatabase 对象的query()方法。

//根据指定条件查询记录,并返回结果数据列表
public List<UserInfoBean> query() {List<UserInfoBean> infoList = new ArrayList<UserInfoBean>();//执行记录查询动作,该语句返回结果集的游标//SELECT语句内容作为 query()方法的参数,比如:要查询的表名,要获取的字段名,WHERE条件,//包含可选的位置参数,去替代WHERE条件中位置参数的值,GROUP BY条件,HAVING条件。//除了表名,其他参数可以是nullCursor cursor = mDB.query(TABLE_NAME, null, null, null, null, null, null);//循环取出游标指向的每条记录while (cursor.moveToNext()) {UserInfoBean info = new UserInfoBean();info._id = cursor.getString(0);//取出字符串info.name = cursor.getString(1);//取出字符串info.age = cursor.getInt(2);//取出整型数info.update_time = cursor.getString(3);//取出字符串infoList.add(info);}cursor.close();// 查询完毕,关闭数据库游标return infoList;
}

方法使用:

userDBHelper.query();

删除数据

使用SQLiteDatabase 对象的delete()方法。

//根据指定条件删除表记录
public int delete(String condition) {//执行删除记录动作,该语句返回删除记录的数目return mDB.delete(TABLE_NAME, condition, null);
}

方法使用:

userDBHelper.delete("_id=12");

未创建表或者删除表后不要对表进行操作报错

1、添加数据失败(Error)程序报错
android.database.sqlite.SQLiteException: no such table: user_info (code 1)

2、删改查数据(AndroidRuntime)程序崩溃
android.database.sqlite.SQLiteException: no such table: user_info (code 1)

各参数说明

table:表名称

colums:列名称数组

selection:条件子句,相当于where

selectionArgs:条件语句的参数数组

groupBy:分组

having:分组条件

orderBy:排序类

limit:分页查询的限制

Cursor:返回值,相当于结果集ResultSet

使用游标

不管你如何执行查询,都会返回一个 Cursor,这是 Android 的 SQLite 数据库游标,使用游标,你可以:  

通过使用 getCount() 方法得到结果集中有多少记录; 

通过 moveToFirst(), moveToNext(), 和 isAfterLast() 方法遍历所有记录;

通过 getColumnNames() 得到字段名;

通过 getColumnIndex() 转换成字段号;

通过 getString(),getInt() 等方法得到给定字段当前记录的值;

通过 requery() 方法重新执行查询得到游标;

通过 close() 方法释放游标资源;

项目实例:SQLiteDemo.zip

Android-SQLite数据库实例相关推荐

  1. android SQLite数据库的使用

    今天,简单讲讲android如何使用SQLite数据库.  最近,自己在做一个功能时又用到了SQLite数据库,发现自己还是掌握的不很全面.其实之前的app里面也一直用到了数据库,但是自己没有花时 ...

  2. Android SQLite 数据库详细介绍

    Android SQLite 数据库详细介绍我们在编写数据库应用软件时,需要考虑这样的问题:因为我们开发的软件可能会安装在很多用户的手机上,如果应用使用到了SQLite数据库,我们必须在用户初次使用软 ...

  3. Android SQLite数据库导出/导入Excel

    Android SQLite数据库导出/导入Excel 前言 框架 使用方法 添加依赖 声明权限 导出数据库到Excel 声明实例 配置导出内容 导出监听 导入Excel到数据库 声明实例 导入监听 ...

  4. android 数据库表格数据库数据库中,Android SQLite数据库中的表详解

    Android SQLite数据库 前言 以前写PHP的时候,内置了print_r()和var_dump()两个函数用于打印输出任意类型的数据内部结构,现在做Android的开发,发现并没有这种类似的 ...

  5. 利用SQLChiper对Android SQLite数据库加密

    利用SQLChiper对Android SQLite数据库加密 前言: 上篇文章讲了Android studio+SQLCipher加密SQLite数据库的几个坑,跳过这几个坑,那么SQLCipher ...

  6. android 获取位置数据库,尝试从webview获取位置时,Android“SQLite数据库无法从/CachedGeoposition.db加载”错误...

    我正在创建一个使用webkit和chrome客户端的android应用程序.我希望能够在网页请求时获取当前位置.我设置的网页适用于普通浏览器就好了.然而,当我尝试访问该网页WebKit中,我不断收到此 ...

  7. Android Sqlite数据库多表联合查询

    Android Sqlite数据库多表联合查询示例 工作上用数据库存储文件还是很便利的,所以有时候发现一张表存储数据感觉数据结构不是很清晰的时候,就需要新加第二张表或者多张表来进行联合查询对象信,一般 ...

  8. Android SQLite数据库版本升级(分逐级升级和跨版本升级)

    参考:Android Sqlite数据库跨版本升级 保存之前数据 本文说的数据库升级是基于Android原生APISQLiteOpenHelper实现的逻辑,不涉及第三方库.其实如果使用官方推荐的Ro ...

  9. android sqlite数据库加密,(转)SQLite数据库的加密

    1.创建空的SQLite数据库. //数据库名的后缀你可以直接指定,甚至没有后缀都可以 //方法一:创建一个空sqlite数据库,用IO的方式 FileStream fs = File.Create( ...

  10. android与mysql数据库同步_android开发 如何通过web服务器访问MYSQL数据库并且使其数据同步到android SQLite数据库?...

    通过web服务器访问MYSQL数据库有以下几个过程: 1.在MySql下创建自己的数据库和自己的表单 2.连接数据库. 3.访问数据库 1.创建web工程 (服务器端) 在Myeclipse下新建一个 ...

最新文章

  1. 2021年华为与小康-北汽-长安
  2. iOS 设置View阴影
  3. webgl(three.js)实现室内定位,楼宇bim、实时定位三维可视化解决方案——第五课
  4. 个人项目【 完成总结】
  5. python处理json数据 乱码报错_python操作mysql中文显示乱码的解决方法
  6. python 的常用时间操作,取得当前时间等
  7. PyCharm中目录directory与包package的区别
  8. Apache POI学习笔记
  9. 解决Amlogic S905或S9xxx在安装Armbian_20.02.0卡logo或无反应的方法
  10. Linux系统中设置静态ip地址
  11. java中web错误返回码,Java-Web3j Transfer.sendFunds()返回错误“天然气...
  12. 易语言怎么给手机发短信
  13. ubuntu18.04播放MP4
  14. 万兆局域网方案_局域网组建实施方案.doc
  15. 单维度量表验证性因子分析_验证性因素分析介绍
  16. python爬虫代理ip
  17. 微信 Android 热补丁实践演进之路
  18. 致远OA漏洞学习——A6版本Session泄漏伪造漏洞
  19. PHP-FPM的PM配置参数说明
  20. SQL注入-bWAPP靶场-时间盲注

热门文章

  1. Building MFC application with /MD[d] (CRT dll vers
  2. app接入支付宝后,支付成功后,回调不响应
  3. 程序员最头疼的七件事
  4. IEEE 802.3简介及各分类标准汇总
  5. 论文投稿指南——收藏|SCI论文投稿注意事项(提高命中率)
  6. jar hell问题以及解决方案
  7. Flutter基础之水平方向列表布局
  8. [LeetCode](面试题 08.11)硬币
  9. Android笔记--自定义控件仿遥控器的圆形上下左右OK圆盘按钮
  10. 出国旅游入乡随俗 看看各国怎么付小费