以前咱们讲了如何将数据存储在文件中,那么除了这种方式呢,就是咱们常见的你们都知道的将数据存储在数据库当中了。sql
将数据存储在数据库中的优点:数据库
1)存储在数据库中的数据更加方便操做,好比增、删、改、查等api
2)能够实现事务的回滚,好比银行转帐等数组
3)方便维护,可读性高安全
4)资源占用少,性能高服务器
5)……微信
SQLite数据库在咱们平常生活中随处不见了,好比咱们的手机~如今市场上的手机都是用SQLite数据库做为数据的存储的。数据结构
以及咱们常看见的智能家居,也是用SQLite数据库去记录数据的。以及咱们常常用到的桌面程序,好比QQ、迅雷等。ide
SQLite数据库是一套开源的嵌入式数据库引擎,它的每一个数据库都是以单个文件的形式存在性能
这些数据以B-Tree的数据结构的形式存储在磁盘上面。
SQLite数据库就是一个很小的、能够直接打开运行的文件,而其余的数据库都是一个大型的应用程序。
使用SQLite的优点:
一、SQLite支持大多数的sql标准语句
增、删、改、查、事务等等,因此这里就不详细的说这个了……
二、轻量级
能够说是袖珍型,然而小小的SQLite却能够支持高达2TB大小的数据库
三、检索速度快
四、动态数据模型(弱类型)
SQLite数据库支持
NULL:空值
INTEGER:整数型
REAL:浮点型
TEXT:字符串文本
BLOB:二进制对象
5个基本数据类型。
之因此称之为“弱类型”,是由于插入数据的时候不论是什么数据类型都会自动的转化。
注意:当INTEGER的约束为PRIMARY KEY时,就必须是整数不会自动转换,不然就会报错!
五、SQLite数据库在使用前不须要安装配置,也不须要启用进程来启动、关闭数据库
六、占用系统资源少
七、跨平台
它能够在多个操做系统下使用而不须要针对某一个操做系统独立编写代码,也就是说它在各各操做系统的数据层是相同的;
同时也是SQLite数据库内在机制决定的,SQL数据库是运行在SQLite虚拟机上面的,
在虚拟机上面会直接转编译成不一样操做系统的数据模型。
SQLite的缺陷在于:
一、不支持大型项目
二、一部分SQL标准语句不支持,可是这些语句通常不会用到……
三、安全性相对于其余大型数据库差
就要比咱们的Android手机,只要获取到root权限,那么也就是证实能够随心所欲了……
那么Android怎么来增强它的安全性呢?
a、提升程序的安全验证
b、增强代码的严谨性
c、权限管理
介于SQLite数据库的优点,不少的桌面应用程序都用它来存储该应用程序的数据;
固然,咱们的Android以及iPhone的产品链也几乎都是运用SQLite数据库。
也就是直接写SQL代码
重写自定义的方法:
1)参数有不少,那么这里简单的只须要context参数就行了。
2)super参数:
context:上下文
name:数据库名称
factory:目的建立cursor对象
version:数据库版本,通常从1开始
onCreate方法:
1)当数据库第一次建立时使用,若是是其次的就是打开
2)适合作表结构的初始化
onUpgrade方法:
1)当数据库的版本升级时使用
2)适合作表结构的更新
execSQL:
要执行的sql语句,这里适用于增、删、改
public class MyOpenHelper extends SQLiteOpenHelper { /** * * @param context 上下文 * name 数据库的名称 * factory 目的建立cursor对象 * version 数据库版本 从1开始 */ public MyOpenHelper(Context context) { super(context, "test_1.db", null, 3); } /** * 当数据库第一次建立是使用 * 这个方法特别适合作表结构的初始化 建立表就是写sql语句 */ @Override public void onCreate(SQLiteDatabase db) { db.execSQL("create table test_info(id integer primary key autoincrement,name varchar(20))"); } /** * 当数据库版本升级时使用 * 这个方法适合作表结构的更新 */ @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("alter table test_info add phone varchar(20)"); } }
1)考虑云端要保存用户【自定义数据、行为习惯】。专业术语profile-->>提升用户黏度
2)考虑当前的最低版本要求-->>下降维护成本
3)尽量本地的数据转移(全部新版本,都不删除字段)-->尽量把未知变已知
4)降级极可能会失败,因此咱们通常 try-catch;当降级成功就是try块的语句,失败以后就执行catch块的语句
5)SQLiteDatabase(执行语句)、oldVersion(老版本号)、newVersion(新版本号)
/* 模拟从3.0 下降会2.0 */ @Override public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) { //正常来说大于2.0的,应该有test_info 这张表,且2.0有的字段,3.0都有 try { //第1、先把test_info 将来的表,更名 String rename_sql = "alter table test_info rename to test_info_bak"; db.execSQL(rename_sql); Log.i("down", "1.更名成功"); //第2、创建2.0的表结构 String sql_message = "create table test_info (id int primary key,tou1 varchar(50),userName varchar(50),
lastMessage varchar(50),datetime varchar(50))"; db.execSQL(sql_message); Log.i("down", "2.创建2.0表结构成功"); //第3、把备份的数据,copy到 新建的2.0的表 String sql_copy = "insert into test_info select id,tou1,userName,lastMessage,datetime from test_info_bak"; db.execSQL(sql_copy); Log.i("down", "3.copy到用户数据到 2.0的表"); //第4、把备份表drop掉 String drop_sql = "drop table if exists test_info_bak"; db.execSQL(drop_sql); Log.i("down", "4.把备份表drop掉"); } catch (Exception e) { //失败 Log.i("hi", "降级失败,从新创建"); String sql_drop_old_table = "drop table if exists test_info"; String sql_message = "create table test_info(id integer primary key autoincrement,name varchar(20),phone varchar(20))"; String sql_init_1 = "insert into test_info values (1,'abc','130000')"; String sql_init_2 = "insert into test_info values (2,'abc','134444')"; db.execSQL(sql_drop_old_table); db.execSQL(sql_message); db.execSQL(sql_init_1); db.execSQL(sql_init_2); } }
myOpenHelper = new MyOpenHelper(getApplicationContext()); //打开或是建立数据库 若是第一次就是建立,其次就是打开 //SQLiteDatabase sqliteDatabase = myOpenHelper.getWritableDatabase(); //打开或是建立数据库 若是第一次就是建立,其次就是打开 若是磁盘满了就返回只读 //SQLiteDatabase sqliteDatabase = myOpenHelper.getReadableDatabase();
//获取数据库对象 SQLiteDatabase db = myOpenHelper.getWritableDatabase(); //执行添加一条sql语句 db.execSQL("insert into test_info(name,phone) values(?,?)",new Object[]{"zhangsan","138888888"}); //数据库用完要关闭 db.close();
SQLiteDatabase db = myOpenHelper.getWritableDatabase(); db.execSQL("delete from test_info where name=?",new Object[]{"zhangsan"}); db.close();
SQLiteDatabase db = myOpenHelper.getWritableDatabase(); db.execSQL("updata test_info set phone=? where name=?",new Object[]{"13777777777","zhangsan"}); db.close();
SQLiteDatabase db = myOpenHelper.getWritableDatabase(); Cursor cursor = db.rawQuery("select * from test_info", null); if(cursor!=null&&cursor.getCount()>0){ while(cursor.moveToNext()){ //columnIndex表明列的索引 String name = cursor.getString(1); String phone = cursor.getString(2); } }
Google工程师给咱们封装好了的一些方法让咱们直接调用,可是其实在底层也就是将这些字符串进行拼接成完整的sql语句。
ContentValues 内部封装好的一个map集合,map集合是以<key,value>的形式存储数据的。
insert参数说明
table:表名
key:对应列的名字
value:对应的值
put参数说明
key:增长的列名字
value:对应的值
//获取数据库对象 SQLiteDatabase db = myOpenHelper.getWritableDatabase(); /** * table 表名 * ContentValues 内部封装了一个map * key:对应列的名字 * value:对应值 */ ContentValues values = new ContentValues(); values.put("name", "wangwu"); values.put("phone", "120"); //返回值表明插入新行的id long insert = db.insert("test_info", null, values);//底层就是在拼接SQL语句 //数据库用完要关闭 db.close(); if(insert>0){ Toast.makeText(getApplicationContext(), "添加成功!", 3000).show(); }else{ Toast.makeText(getApplicationContext(), "添加失败!", 3000).show(); }
delete参数说明
table:表名
whereClause:要删除的是哪一列,根据什么删除
whereArgs:这里返回的是一个数组对象,根据删除列的值
SQLiteDatabase db = myOpenHelper.getWritableDatabase(); //根据Google封装好的api删除 int delete = db.delete("test_info", "name=?", new String[]{"wangwu"}); db.close(); Toast.makeText(getApplicationContext(), "删除了"+delete+"行", 2000).show();
update参数说明
table:表名
value:就是ContentValues中的value
whereClause:要修改的是哪一列,根据什么修改
whereArgs:这里返回的是一个数组对象,根据修改列的值
SQLiteDatabase db = myOpenHelper.getWritableDatabase();
//根据Google封装好的api修改 ContentValues value = new ContentValues(); value.put("phone", "110"); //表明更新了多少行 int updata = db.update("test_info", value, "name=?", new String[]{"wangwu"}); db.close(); Toast.makeText(getApplicationContext(), "更新了"+updata+"行", 2000).show();
query参数说明
table:表名
columns:查询的列
selection:根据什么查询
selectionArgs:查询的条件的值
groupBy:分组
having:查询条件,这里要区分having与where的区别!
orderBy:排序
moveToNext():遍历数据表中的数据
cursor:Google工程师封装好的指针对象,用于遍历集合下标
SQLiteDatabase db = myOpenHelper.getWritableDatabase(); /** * 根据Google封装好的api查询 * columns 表明你要查询的列 * selection 根据什么查询phone */ Cursor cursor = db.query("test_info", new String[]{"phone"}, "name=?", new String[]{"wangwu"}, null, null, null); if(cursor!=null&&cursor.getCount()>0){ while(cursor.moveToNext()){ String phone = cursor.getString(0); System.out.println("phone:" + phone); } }
1)能够更加灵活运用sql语句
2)代码量能够减小,效率更高
1)容易写错sql代码
2)很差维护
1)不用直接写sql语句,减小了错误的几率
2)方便维护
1)使程序更加笨重,效率低
2)不方便数据的操做,不能灵活运用数据的操做语句
不论是使用哪种方法,都有它的好处和坏处,因此在实际开发中视实际状况而定,想用什么方法也都是可行的。
建议:比较小型的程序推荐使用封装好的api,比较简单,能够提升开发效率
比较大型的程序推荐使用原生方法,比较灵活,也能够提升程序效率
一、使用SQLite的优缺点
二、数据库的升级和降级(*****)
三、使用原生方法对数据库进行简单操做
四、使用Google封装好的api对数据库进行简单操做
五、各自的优缺点
六、Android和iPhone产品链的数据层是同样的
ps:感兴趣的同窗能够想一想微信:
在客户端的SQLite是怎么去实现的?
在后台服务器使用什么去实现的,又是如何实现的?
那么又要作到这些数据的交互呢?
又是怎样去优化的呢?