以前咱們講了如何將數據存儲在文件中,那麼除了這種方式呢,就是咱們常見的你們都知道的將數據存儲在數據庫當中了。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是怎麼去實現的?
在後臺服務器使用什麼去實現的,又是如何實現的?
那麼又要作到這些數據的交互呢?
又是怎樣去優化的呢?