<font color=FF0000> LZ-Says:給大家推薦一個網(wǎng)站沼头,有興趣可以查閱,想為大家貢獻一點自己的力量也可以投稿机断,老大審核通過會發(fā)表盟猖,更好的幫助有需要的人歡迎大家踴躍投稿地址如下:
http://www.123si.org/android
當年 <font color=#FF0000 size=4 >豪放</font> 愛自由担巩,而今 <font color=#DAA520 size=4 >闊步</font> 向前(錢)看~誰還沒個 <font color=#0000FF size=4 >年少輕狂</font> 方援!
1. SQLite 簡介
1-1 SQLite 介紹
SQLite,是一款輕型的數(shù)據(jù)庫涛癌,是遵守ACID的關(guān)系型數(shù)據(jù)庫管理系統(tǒng)犯戏,它包含在一個相對小的C庫中送火。
它設(shè)計目標是嵌入式,力求占用資源較低先匪,處理速度較快种吸;它支持Windows/Linux/Unix等等主流的操作系統(tǒng),同時也支持很多語言(Java呀非,php坚俗,.Net等)。
總的來說岸裙,<font color=#FF0000 size=4 >SQLite是一個軟件庫猖败,實現(xiàn)了自給自足的、無服務(wù)器的降允、零配置的恩闻、事務(wù)性的 SQL 數(shù)據(jù)庫引擎</font>。
1-2 SQLite 歷史
- 2000 -- D. Richard Hipp 設(shè)計 SQLite 是為了不需要管理即可操作程序剧董;
- 2000 -- 在八月幢尚,SQLite1.0 發(fā)布 GNU 數(shù)據(jù)庫管理器(GNU Database Manager);
- 2011 -- Hipp 宣布翅楼,向 SQLite DB 添加 UNQl 接口尉剩,開發(fā) UNQLite(面向文檔的數(shù)據(jù)庫)
1-3 SQLite 局限性
在 SQLite 中,SQL92 不支持的特性如下所示:
2. SQLite 優(yōu)點及缺點
2-1 SQLite 優(yōu)點
動態(tài)數(shù)據(jù)類型存儲:采用無數(shù)據(jù)類型犁嗅,所以可以保存任何類型的數(shù)據(jù)边涕,會根據(jù)存入值自動判斷(<font color=#FF0000 >一般推薦指定類型為好</font>);
輕量級
綠色軟件:核心引擎本身不依賴第三方的軟件褂微,使用它也不需要“安裝”功蜓,無需各種瑣碎配置 ;
單一文件:數(shù)據(jù)庫中所有的信息(比如表宠蚂、視圖式撼、觸發(fā)器、等)都包含在一個文件內(nèi)求厕,方便移植著隆;
跨平臺/可移植性
支持多語言編程接口
開源,免費
呀癣。美浦。。 项栏。浦辨。。
2-2 SQLite 缺點
并發(fā)訪問的鎖機制:數(shù)據(jù)庫可能會被寫操作獨占沼沈,從而導致其他讀寫操作阻塞或出錯流酬;
SQL標準支持不全币厕;
網(wǎng)絡(luò)文件系統(tǒng)(NFS)并發(fā)讀寫可能會出問題: SQLite文件放置于NFS時,在并發(fā)讀寫的情況下可能會出問題(比如數(shù)據(jù)損壞)芽腾。原因<font color=#FF0000 >據(jù)說是由于某些NFS的文件鎖實現(xiàn)上有Bug</font>旦装。
3. SQLite 數(shù)據(jù)類型
我們在上面曾說過,SQLite采用的是動態(tài)數(shù)據(jù)類型存儲摊滔,它擁有基本數(shù)據(jù)類型阴绢,同時也關(guān)聯(lián)親和(Affinity)類型,具體說明如下:
3-1 基本數(shù)據(jù)類型
3-2 親和(Affinity)類型
SQLite支持列的親和類型概念艰躺。任何列仍然可以存儲任何類型的數(shù)據(jù)旱函,當數(shù)據(jù)插入時,該字段的數(shù)據(jù)將會優(yōu)先采用親緣類型作為該值的存儲方式描滔。
SQLite目前的版本支持以下五種親緣類型:
3-3 數(shù)據(jù)類型名稱以及相應(yīng)的親和類型:
3-4 存儲時間類型技巧
4. Android 官方提供常用方法
Android提供了創(chuàng)建和使用 SQLite 數(shù)據(jù)庫的 API 棒妨。SQLiteDatabase 代表一個數(shù)據(jù)庫對象,提供了操作數(shù)據(jù)庫的一些方法含长。
下面我們分別去了解下Android為我們提供這些API的常用內(nèi)容券腔。
4-1 SQLiteOpenHelper 常用方法簡述
- 1. void onCreate(SQLiteDatabase db): 在首次生成數(shù)據(jù)庫時才會被調(diào)用,在onCreate()方法里可以生成數(shù)據(jù)庫表結(jié)構(gòu)等相關(guān)初始化操作拘泞。
- 2. void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion): 在數(shù)據(jù)庫的版本發(fā)生變化時會被調(diào)用纷纫,一般在軟件升級時才需改變版本號,或者說由于需求的變化導致不得不對數(shù)據(jù)庫相關(guān)屬性(字段)陪腌,那么這時候可以在這里面做相關(guān)操作辱魁。
4-2 SQLiteDatabase 常用方法簡述
<font size=3 >1. 獲取操作數(shù)據(jù)庫的SQLiteDatabase實例</font>
- getReadableDatabase()
先以讀寫方式打開數(shù)據(jù)庫,如果數(shù)據(jù)庫的磁盤空間滿了诗鸭,就會打開失敗染簇,當打開失敗后會繼續(xù)嘗試以只讀方式打開數(shù)據(jù)庫。如果該問題成功解決强岸,則只讀數(shù)據(jù)庫對象就會關(guān)閉锻弓,然后返回一個可讀寫的數(shù)據(jù)庫對象。- getWritableDatabase()
以讀寫方式打開數(shù)據(jù)庫蝌箍,一旦數(shù)據(jù)庫的磁盤空間滿了青灼,數(shù)據(jù)庫就只能讀而不能寫
繼續(xù)深入了解,我們發(fā)現(xiàn)他們內(nèi)部調(diào)用同一個方法妓盲,同樣是獲取數(shù)據(jù)庫的SQLiteDatabase實例杂拨,只不過二者之間對異常處理的方式不一樣。
<font size=3 >2. 新增</font>
- <font color=#FF0000 >long insert(String table, String nullColumnHack, ContentValues values)</font>
- long insertOrThrow(String table, String nullColumnHack, ContentValues values)
- long insertWithOnConflict(String table, String nullColumnHack, ContentValues initialValues, int conflictAlgorithm)
官方為我們提供了以上三種方式去實現(xiàn)新增操作悯衬,頻繁使用的也就是第一種方式弹沽,通過查閱源碼得知,<font color=#FF0000 >insert()和insertOrThrow()最終都會調(diào)用insertWithOnConflict()</font>。
為了避免大家說我扯犢子贷币,把找到的證據(jù)擺上來:
也就是說最后都會通過調(diào)用insertWithOnConflict()去做處理,也就是進行新增操作亏狰。接下來我們再簡單聊聊參數(shù)相關(guān)含義役纹,如下:
table:要插入數(shù)據(jù)的表的名稱;
values:一個ContentValues對象暇唾,類似一個map.通過鍵值對的形式存儲值促脉;
conflictAlgon:沖突解決方案。例如當數(shù)據(jù)表主鍵的唯一性檢測出錯的時候策州,就會按照該值設(shè)定的值進行處理瘸味;
nullColumnHack:當values參數(shù)為空或者里面沒有內(nèi)容的時候,我們insert是會失敗的(底層數(shù)據(jù)庫不允許插入一個空行)够挂,為了防止這種情況旁仿,我們要在這里指定一個 列名,到時候如果發(fā)現(xiàn)將要插入的行為空行時孽糖,就會將你指定的這個列名的值設(shè)為null枯冈,然后再向數(shù)據(jù)庫中插入
方法返回值含義: <font color=#FF0000>方法返回當前插入的索引。</font>
<font size=3 >3. 刪除</font>
- int delete(String table, String whereClause, String[] whereArgs)
參數(shù)解釋如下:
whereClause:條件办悟,為一個字符串尘奏;如果多個條件中間使用 and 隔開;
whereArgs:字符串數(shù)組病蛉,和whereClause配合使用炫加。與條件匹配的值。
<font size=3 >4. 修改</font>
- int update(String table, ContentValues values, String whereClause, String[] whereArgs)
- int updateWithOnConflict(String table, ContentValues values,String whereClause, String[] whereArgs, int conflictAlgorithm)
我們普遍使用的是update()方法铺然,但是它內(nèi)部會調(diào)用updateWithOnConflict()去實現(xiàn)更新操作俗孝,有興趣的可以了解了解
<font size=3 >5. 查詢</font>
- Cursor query(String table, String[] columns, String selection,String[] selectionArgs, String groupBy, String having,String orderBy);
- Cursor query(boolean distinct, String table, String[] columns,String selection, String[] selectionArgs, String groupBy,String having, String orderBy, String limit)魄健;
- Cursor query(boolean distinct, String table, String[] columns,String selection, String[] selectionArgs, String groupBy,String having, String orderBy, String limit, CancellationSignal cancellationSignal)驹针;
- Cursor query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having,String orderBy, String limit);
- Cursor rawQuery(String sql, String[] selectionArgs)诀艰;
- Cursor rawQuery(String sql, String[] selectionArgs, CancellationSignal cancellationSignal)柬甥;
- Cursor <font color=#FF0000>rawQueryWithFactory</font>( CursorFactory cursorFactory, String sql, String[] selectionArgs,String editTable);
查詢最終依然調(diào)用了rawQueryWithFactory()其垄,主要的操作還是在這里面實現(xiàn)苛蒲。其中相關(guān)的參數(shù)大家可以從字面上理解,這點不得不說谷歌編碼還是很6的
以上的方法都是基于實用官方封裝好的方法绿满,那么有的兄弟問了臂外,我想直接使用SQL語句怎么弄,比較封裝好的內(nèi)部也是通過拼接SQL去實現(xiàn)功能的,別急漏健,官方在查詢中同樣也提供了SQL語句方式嚎货,大家注意看上面,下面簡單介紹下execSQL()~
execSQL(String sql, Object[] bindArgs):方法的第一個參數(shù)為SQL語句蔫浆,第二個參數(shù)為SQL語句中占位符參數(shù)的值殖属,參數(shù)值在數(shù)組中的順序要和占位符的位置對應(yīng)。
通過查看源碼瓦盛,我們可以得知此方法是void類型洗显,也就是說無返回!大家注意原环。
下面為大家舉個小例子挠唆,如下:
//省略初始化操作
方法一:指定列名
db.execSQL("insert into stu(stu_name,stu_age,stu_address) values(?,?,?)", new Object[]{"賀大寶",21,"目前在廊坊~"});
方法二:不指定列名
db.execSQL("insert into stu values(?,?,?)", new Object[]{"賀大寶",21,"目前在廊坊~"});
//省略關(guān)閉操作
5. 常用 SQL 語句
<font color=#FF0000 size=4>注意:SQL 語句對大小寫不敏感</font>
5-1 基本 SQL 語句
- insert --- 插入
寫法一: insert into table_name values (值1, 值2,....)
寫法二: insert into table_name values (列1, 列2,...) values(值1, 值2,....)<font color=#FF0000 >(需注意的是,值需要和列一一對應(yīng))</font>
- delete --- 刪除
刪除符合條件數(shù)據(jù):delete from table_name where 列名稱=值
刪除表中所有數(shù)據(jù):delete from table_name
- update --- 修改
修改一列:update table_name set 列名稱 = 新值 where 列名稱 = 某值
修改多列:update table_name set 列名稱1 = 新值1嘱吗,列名稱2 = 新值2 where 列名稱 = 某值
- select --- 查詢
查詢某表中所有數(shù)據(jù):select * from table_name
查詢某表中指定列數(shù)據(jù):select 列名稱 from table_name
查詢去除重復數(shù)據(jù):select distinct 列名稱 from table_name
- order by --- 排序
order by 語句用于根據(jù)指定的列對結(jié)果集進行排序玄组;
order by 語句默認按照升序?qū)τ涗涍M行排序,如果希望按照降序?qū)τ涗涍M行排序谒麦,可以使用 desc 關(guān)鍵字巧勤。
附上一張例子圖:
5-2 常用 SQL 函數(shù)
- avg() --- 返回數(shù)值列的平均值(null 值不包括在計算中)
select avg(column_name) from table_name
- count() --- 返回指定列的值的數(shù)目(null 不計入)
表中的記錄數(shù):select count(*) from table_name
返回指定列的值的數(shù)目:select count(column_name) from table_name
- max() --- 返回一列中的最大值(null 值不包括在計算中)
select max(column_name) from table_name
- min() --- 返回一列中的最小值(null 值不包括在計算中)
select min(column_name) from table_name
- sum() --- 返回數(shù)值列的總數(shù)
select sum(column_name) from table_name
- first() --- 返回指定的字段中第一個記錄的值
select first(column_name) from table_name
- last() --- 返回指定的字段中最后一個記錄的值
select last(column_name) from table_name
6. 讓我們愉快的開始擼碼之旅吧~
我們在上面說過,官方為我們提供了 SQLiteOpenHelper 去方便我們簡單弄匕,快速創(chuàng)建數(shù)據(jù)庫以及基本表颅悉,那么具體實現(xiàn)又是怎么樣的呢?看下面高能熱量~
6-1 創(chuàng)建DBHelper幫助類
package cn.hlq.sqlitestudy.db;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
/**
* Created by HLQ on 2017/4/7
* 創(chuàng)建數(shù)據(jù)庫(初始化)幫助類
* 現(xiàn)在創(chuàng)建一個學生表迁匠,表中含有編號剩瓶,姓名,年齡城丧,地址
*/
public class DBHelper extends SQLiteOpenHelper {
/**
* 數(shù)據(jù)庫名稱
*/
private static final String DATABASE_NAME="sqlite_study.db";
/**
* 數(shù)據(jù)庫版本號
*/
private static final int DATABASE_VERSION=1;
/**
* 初始化設(shè)置數(shù)據(jù)庫名稱延曙,數(shù)據(jù)庫版本號
* @param context
*/
public DBHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
/**
* 鍵明其意,在創(chuàng)建的時候會調(diào)用亡哄,而且只會調(diào)用一次
* @param db
*/
@Override
public void onCreate(SQLiteDatabase db) {
// 創(chuàng)建學生表
db.execSQL(SQLManager.SQL_CREATE_TABLE_STU);
}
/**
* 數(shù)據(jù)庫有更新時調(diào)用
* @param db
* @param oldVersion
* @param newVersion
*/
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
6-2 創(chuàng)建SQLManager管理類
為了后期方便拓展枝缔,我們可以將SQL語句歸為一個類,單獨管理
package cn.hlq.sqlitestudy.db;
/**
* Created by HLQ on 2017/4/7
* 這里為了避免累贅蚊惯,簡單附上創(chuàng)建學生表的SQL語句愿卸,具體詳情大家可直接查看Demo源碼
*/
public class SQLManager {
/**
* 創(chuàng)建學生表
*/
public static final String SQL_CREATE_TABLE_STU="create table if not exists stu (stu_id integer primary key autoincrement,stu_name varchar(15),stu_age integer,stu_address varchar(50))";
}
6-3 創(chuàng)建DBManager管理類,實現(xiàn)CRUD
package cn.hlq.sqlitestudy.db;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
import cn.hlq.sqlitestudy.entity.Student;
/**
* Created by HLQ on 2017/4/7
*/
public class DBManager {
private Context context;
private DBHelper helper;
private SQLiteDatabase db;
/**
* 構(gòu)造方法初始化
*
* @param context
*/
public DBManager(Context context) {
this.context = context;
this.helper = new DBHelper(context);
this.db = helper.getWritableDatabase();
}
/**
* 新增一條數(shù)據(jù)
*
* @param stu
* @return
*/
public long insertDB(Student stu) {
ContentValues values = new ContentValues();
values.put("stu_name", stu.getStuName());
values.put("stu_age", stu.getStuAge());
values.put("stu_address", stu.getStuAddress());
long rowsNum = 0;
try {
rowsNum = db.insert("stu", null, values);
} catch (Exception e) {
e.printStackTrace();
Log.e("HLQ_Struggle", "insert error:" + e.getMessage());
} finally {
if (db != null) {
db.close();
}
}
return rowsNum;
}
/**
* 刪除單條數(shù)據(jù)
*
* @param stuName
* @return
*/
public int deleteDB(String stuName) {
int rowsNum = 0;
try {
rowsNum = db.delete("stu", "stu_name=?", new String[]{stuName});
} catch (Exception e) {
e.printStackTrace();
Log.e("HLQ_Struggle", "delete error:" + e.getMessage());
} finally {
if (db != null) {
db.close();
}
}
return rowsNum;
}
/**
* 刪除多條數(shù)據(jù)
*
* @param stuName
* @param stuAge
* @return
*/
public int deleteDBForWhere(String stuName, int stuAge) {
int rowsNum = 0;
try {
rowsNum = db.delete("stu", "stu_name=? and stu_age=?", new String[]{stuName, stuAge + ""});
} catch (Exception e) {
e.printStackTrace();
Log.e("HLQ_Struggle", "delete more where error:" + e.getMessage());
} finally {
if (db != null) {
db.close();
}
}
return rowsNum;
}
/**
* 根據(jù)姓名修改
*
* @param stuName
* @return
*/
public int updateDB(String stuName) {
ContentValues values = new ContentValues();
values.put("stu_name", "Test");
int rowsNum = 0;
try {
rowsNum = db.update("stu", values, "stu_name=?", new String[]{stuName});
} catch (Exception e) {
e.printStackTrace();
Log.e("HLQ_Struggle", "update error:" + e.getMessage());
} finally {
if (db != null) {
db.close();
}
}
return rowsNum;
}
/**
* 查詢所有數(shù)據(jù)
*
* @return
*/
public List<Student> queryStu() {
List<Student> stuList = new ArrayList<>();
Cursor cursor = null;
try {
cursor = db.query("stu", null, null, null, null, null, null);
if (cursor != null) {
while (cursor.moveToNext()) {
Student stu = new Student();
stu.setStuName(cursor.getString(cursor.getColumnIndex("stu_name")));
stu.setStuAge(cursor.getInt(cursor.getColumnIndex("stu_age")));
stu.setStuAddress(cursor.getString(cursor.getColumnIndex("stu_address")));
stuList.add(stu);
}
}
} catch (Exception e) {
e.printStackTrace();
Log.e("HLQ_Struggle", "query error:" + e.getMessage());
} finally {
if (cursor != null) {
cursor.close();
}
if (db != null) {
db.close();
}
}
return stuList;
}
}
都說眼見為實截型,那么讓我們一起看看運行結(jié)果趴荸。
運行結(jié)果大展示
- 新增一條數(shù)據(jù)
新增成功,看看數(shù)據(jù)庫中數(shù)據(jù)是否正確宦焦。
- 根據(jù)一個條件刪除數(shù)據(jù)
刪除成功发钝,看看數(shù)據(jù)庫中數(shù)據(jù)是否正確顿涣。
- 根據(jù)多個條件刪除數(shù)據(jù)
首先查看下數(shù)據(jù)庫目前存儲數(shù)據(jù)內(nèi)容
接下來要對姓名為“張三”,年齡為“18”的數(shù)據(jù)進行刪除酝豪,結(jié)果如下:
再次查看數(shù)據(jù)庫中數(shù)據(jù)
- 根據(jù)條件修改數(shù)據(jù)
修改成功涛碑,看看數(shù)據(jù)庫中數(shù)據(jù)是否正確
- 查詢結(jié)果展示
7. 使用注意項以及相關(guān)技巧
7-1 創(chuàng)建表以及屬性(字段)需注意避免使用 <font color=#FF0000 >關(guān)鍵字</font>
官方給出關(guān)鍵字如下:
這里寫圖片描述大家使用過程中可以取第一位前綴或者單詞,例如孵淘,Stu表中id可以寫成 s_id or stu_id蒲障,這樣感覺一下子就明確多了。
7-2 創(chuàng)建表使用關(guān)鍵字 <font color=#FF0000 >if not exists</font>
使用普通創(chuàng)建表可能會返回創(chuàng)建失敗夺英,原因可能是表已存在,而是用if not exists滋捶,如果不存在才會創(chuàng)建痛悯,保證程序健壯性。
7-3 讀取或者查詢完之后 <font color=#FF0000 >記得關(guān)閉游標或者數(shù)據(jù)庫重窟,防止內(nèi)存泄漏</font>
8. 代碼查看及下載
GitHub 查看地址:https://github.com/HLQ-Struggle/SQLiteStudy
Demo 下載地址:http://download.csdn.net/detail/u012400885/9807179
9. 參考資料
感謝如下各位同仁奉獻(前人栽樹载萌,后人乘涼),Thanks:
2. http://www.runoob.com/sqlite/sqlite-tutorial.html ;
3. http://blog.sina.com.cn/s/blog_8cfbb9920100zetj.html扭仁;
4. http://blog.knowsky.com/185331.htm;
5. http://www.w3school.com.cn/sql/index.asp ;
6. http://blog.csdn.net/imxilife/article/details/45620009厅翔;
7. http://blog.csdn.net/primer_programer/article/details/28513919乖坠;