SQLite數據庫
SQLite簡介:
Sqlite是一款輕量級的關係型數據庫。關係型數據庫以行和列的形式存儲數據,以便於用戶理解。
關係型數據庫:是指採用了關係模型來組織數據的數據庫
非關係型數據庫:網狀模型、對象模型、半結構化模型等。
SQLite是無類型的,定義類型只是爲了方便程序員查看,可以在integer中添加字符串。
Android中如何管理SQLite:
在android系統中,提供了一個SQLiteOpenHelper抽象類,用於對數據庫進行操作。
/**
* Created by gj on 2016/4/21.
* Message消息信息數據庫幫助類
*/
public class MessageDBOpenHelper extends SQLiteOpenHelper {
/**
* context 上下文對象,
* 數據庫名稱
* 遊標結果集工廠。null使用android默認的
* 數據庫版本號,必須大於1
*/
public MessageDBOpenHelper(Context context) {
super(context, "phonekeymes.db", null, 1);
}
/**
* 數據庫創建,數據庫第一次創建時調用。
* @param db The database.
*/
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table messageinfo(_id integer primary key autoincrement,accountToken varchar(40),subname varchar(40),comeType varchar(20),mesType varchar(20),msg varchar(512),time varchar(20),code integer,isRead varchar(2))");
db.execSQL("create table message_flag(_id integer primary key autoincrement,accountToken varchar(40),code varchar(20))");
}
/**
* 數據庫版本升級時回調
* @param db The database. 當前數據庫對象,
* @param oldVersion The old database version.老版本號
* @param newVersion The new database version.新版本號
*/
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//更新表結構
// if(oldVersion ==1&& newVersion==2){
// db.execSQL("alter table add column isdelete integer");
// }
}
}
數據庫版本號必須大於1,不大於1會拋出異常
public SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version, DatabaseErrorHandler errorHandler) { if (version < 1) throw new IllegalArgumentException("Version must be >= 1, was " + version); …… }
SQLiteOpenHelper.getWritableDatabase可以拿到數據庫對象SQLiteDatabase
遇到的問題:
相同的名稱的數據庫,兩張表,使用了兩個SQLiteOpenHelper對象,分別進行創建表。
當執行過一次表的操作後,執行第二張表的操作時,會報找不到這個表 no such table
後來把同一個數據庫的建表放到同一個SQLiteOpenHelper中。問題解決。
理解:同一個數據庫即一個文件,當有SQLiteOpenHelper類操作這個文件時。再來訪問同一個表,即報錯。
操作數據庫SQLiteDatabase
Android提供了一個SQLiteDatabase的類,該類封裝了一些操作數據庫的API,使用該類可以完成對數據進行增刪改查操作。CRUD
SQLiteDatabase
execSQL(“sql語句”);可以執行insert、delete、update和create table之類有更改行爲的sql語句
rawQuery(“sql語句”);用於執行select語句。
增刪改查
package cn.gyyx.phonekey.util.db.dao; /** * Created by gj on 2016/4/21. */ public class MessageInfoDao { private MessageDBOpenHelper helper; /** * 只有一個有參的構造方法,要求必須傳入上下文 * @param context */ public MessageInfoDao(Context context) { helper = new MessageDBOpenHelper(context); } /** * 添加一條數據 */ public void add(MessageInfo msgeInfo){ SQLiteDatabase db = helper.getWritableDatabase(); db.execSQL("insert into messageinfo(accountToken,subname,comeType,mesType,msg,time,code,isRead) values (?,?,?,?,?,?,?,?)", new Object[]{msgeInfo.accountToken,msgeInfo.subName,msgeInfo.comeType,msgeInfo.mesType,msgeInfo.msg,msgeInfo.time,msgeInfo.flagCode,msgeInfo.isRead?1:0}); db.close();//釋放資源 helper.close(); } /** * 根據token刪除數據 * @param token */ public void deleteByAccountToken(String token){ SQLiteDatabase db = helper.getWritableDatabase(); db.execSQL("delete from messageinfo where accountToken=?",new Object[]{token}); db.close(); helper.close(); } /** * 刪除所有消息數據 */ public void deleteAllMes(){ SQLiteDatabase db = helper.getWritableDatabase(); db.execSQL("delete from messageinfo",new Object[]{}); db.close(); helper.close(); } /** * 添加集合數據 */ public void insertList(List<MessageInfo> list){ SQLiteDatabase db = helper.getWritableDatabase(); db.beginTransaction(); try{ for(MessageInfo msgeInfo:list){ //先判斷是否存在 if(selectByTokenAndCode(db,msgeInfo.accountToken,msgeInfo.flagCode)){ }else{ db.execSQL("insert into messageinfo(accountToken,subname,comeType,mesType,msg,time,code,isRead) values (?,?,?,?,?,?,?,?)", new Object[]{msgeInfo.accountToken,msgeInfo.subName,msgeInfo.comeType,msgeInfo.mesType,msgeInfo.msg,msgeInfo.time,msgeInfo.flagCode,msgeInfo.isRead?1:0}); } } db.setTransactionSuccessful(); }catch(Exception e){ e.printStackTrace(); }finally { db.endTransaction(); db.close(); helper.close(); } } /** * 根據當前token和code 更新狀態爲已讀 * @param token * @param code * @return */ public void updataReadByTokenAndCode(String token,String code){ SQLiteDatabase db = helper.getReadableDatabase(); db.execSQL("update messageinfo set isRead = ? where accountToken = ? and code = ?", new String[]{"1", token, code}); db.close(); helper.close(); } /** * 判斷當前token和code 信息是否已存在 * @param db * @param token * @param code * @return */ private boolean selectByTokenAndCode(SQLiteDatabase db,String token,String code){ Cursor cursor = db.rawQuery("select * from messageinfo where accountToken = ? and code = ?",new String[]{token,code}); if(cursor.getCount()>0){ return true; } return false; } /** * 獲取全部的消息信息 * @return List<MessageInfo> */ public List<MessageInfo> findAll(){ List<MessageInfo> messageInfos =new ArrayList<MessageInfo>(); SQLiteDatabase db = helper.getReadableDatabase(); Cursor cursor = db.rawQuery("select * from messageinfo order by code desc", null); while(cursor.moveToNext()){ MessageInfo messageInfo = new MessageInfo(); messageInfo.accountToken = cursor.getString(cursor.getColumnIndex("accountToken")); messageInfo.comeType = cursor.getString(cursor.getColumnIndex("comeType")); messageInfo.mesType = cursor.getString(cursor.getColumnIndex("mesType")); messageInfo.msg = cursor.getString(cursor.getColumnIndex("msg")); messageInfo.time = cursor.getString(cursor.getColumnIndex("time")); messageInfo.flagCode = cursor.getString(cursor.getColumnIndex("code")); messageInfo.isRead = "1".equals(cursor.getString(cursor.getColumnIndex("isRead")))?true:false; messageInfo.subName = cursor.getString(cursor.getColumnIndex("subname")); messageInfos.add(messageInfo); LogUtil.e("gj",messageInfo.toString()); } cursor.close(); db.close(); helper.close(); return messageInfos.size()>0?messageInfos:null; } }
遊標結果集:Cursor
遊標指向獲取到的數據集合的前面
Cursor.moveToNext();將遊標移動到下一行,如果移過了最後一行返回false。否則返回true
moveToFirst();移動到第一行,返回boolean
moveToLast();移動到最後一行,返回boolean
cursor.close();關閉遊標
事務使用:
事務是什麼:
事務就是指一批sql操作,一塊執行,要麼都成功,要麼都失敗。
爲什麼用事務:
1. 提高效率,單獨使用插入一條一條的語句,插入一次就是一次磁盤的寫入操作,效率會很低。使用事務是在進行事務提交時,將要執行的Sql操作一次性打開數據庫連接並執行。(sqlite中)
2. 當執行一批sql操作時,可能會有失敗的。前面失敗,後面的成功。會造成一些不可控的問題。
主要方法:
beginTransaction();開啓一個事務
setTransactionSuccessful();設置成功標記
endTransaction();結束事務,根據標記提交或回滾。
Android自身對SQL語句的封裝:
SQLiteDatabase db =helper.getWritableDatabase(); ContentValues values = new ContentValues(); values.put("code","1212"); values.put("accountToken","44454345");
//插入 db.insert("表名", "列名", values);
//刪除 db.delete("表名", "accountToken =?", new String[]{"44454345"});
//更新 db.update("表名", values, "accountToken=?", new String[]{"1212212"});
//查詢,通過code排序降序 Cursor cursor = db.query("表名",new String[]{"code"},"accountToken = ?",new String[]{"1212212"},null,null,"code desc");
//查詢所有 Cursor cursor1 = db.query("表名",new String[]{"code"},null,null,null,null,null);
insert
insert into 表名(column1,column2) values(value1,value2)
delete
delete fromtableName where column1 = value1
update
update tableNameset column1 = value1 where column2 = value2
select
select * fromtableName
select * fromtableName where column1>100 order by column2 desc
問題
1.能存儲byte嗎?
直接存進去轉出來有問題。需要做特殊處理
2.數據庫版本降級?
Caused by:android.database.sqlite.SQLiteException: Can't downgrade database from version2 to 1
3.b-tree是啥?
百度:B-tree(多路搜索樹,並不是二叉的)是一種常見的數據結構。使用B-tree結構可以顯著減少定位記錄時所經歷的中間過程,從而加快存取速度。按照翻譯,B 通常認爲是Balance的簡稱。這個數據結構一般用於數據庫的索引,綜合效率較高。
1.student表,插入age 18,name“xiao王”?
insert intostudent (age,name) values(18,’xiao王’)
2.更新student xiao王 年齡爲16?
update student setage=16 where name=’xiao王’ and age=18
3.刪除student 年齡大於15的 所有行
delete fromstudent where age>15
4.查詢所有student 年齡小於20的,年齡倒敘。
select * fromstudent where age<20 order by age desc