SQLlite在安卓中的基本详解和简单使用
一、基礎(chǔ)介紹
1.SQLite 是一個進(jìn)程內(nèi)的庫,是一種輕量級的、自給自足的、無服務(wù)器的、無需配置的,事務(wù)性的SQL數(shù)據(jù)庫引擎.和他其他的數(shù)據(jù)庫一樣,SQLite引擎不是一個獨立的進(jìn)程,可以按應(yīng)用程序需求進(jìn)行靜態(tài)或動態(tài)連接。SQLite可以直接訪問其存儲文件。
SQLite是一個開源的嵌入式關(guān)系數(shù)據(jù)庫,它在2000年由D. Richard Hipp發(fā)布,用C語言編寫的開源嵌入式數(shù)據(jù)庫引擎,它的減少應(yīng)用程序管理數(shù)據(jù)的開銷,SQLite可移植性好,很容易使用,很小,高效而且可靠。它支持大多數(shù)的SQL92標(biāo)準(zhǔn),并且可以在所有主要的操作系統(tǒng)上運(yùn)行。
SQLite嵌入到使用它的應(yīng)用程序中,它們共用相同的進(jìn)程空間,而不是單獨的一個進(jìn)程。從外部看,它并不像一個RDBMS,但在進(jìn)程內(nèi)部,它卻是完整的,自包含的數(shù)據(jù)庫引擎。嵌入式數(shù)據(jù)庫的一大好處就是在你的程序內(nèi)部不需要網(wǎng)絡(luò)配置,也不需要管理。因為客戶端和服務(wù)器在同一進(jìn)程空間運(yùn)行。
SQLite 的數(shù)據(jù)庫權(quán)限只依賴于文件系統(tǒng),沒有用戶帳戶的概念。SQLite 有數(shù)據(jù)庫級鎖定,沒有網(wǎng)絡(luò)服務(wù)器。它需要的內(nèi)存,其它開銷很小,適合用于嵌入式設(shè)備。你需要做的僅僅是把它正確的編譯到你的程序。
2.SQLite 是一個開源的嵌入式關(guān)系數(shù)據(jù)庫。 其特點是高度便攜、使用方便、結(jié)構(gòu)緊湊、高效、可靠。 與其他數(shù)據(jù)庫管理系統(tǒng)不同,SQLite 的安裝和運(yùn)行非常簡單,在大多數(shù)情況下 - 只要確保SQLite的二進(jìn)制文件存在即可開始創(chuàng)建、連接和使用數(shù)據(jù)庫。如果您正在尋找一個嵌入式數(shù)據(jù)庫項目或解決方案,SQLite是絕對值得考慮。
3、SQLite的特點(SQLite’s Features and Philosophy)?
3.1、零配置(Zero Configuration)?
3.2、可移植(Portability):?
它是運(yùn)行在Windows,Linux,BSD,Mac OS X和一些商用Unix系統(tǒng),比如Sun的Solaris,IBM的AIX,同樣,它也可以工作在許多嵌入式操作系統(tǒng)下,比如QNX,VxWorks,Palm OS, Symbin和Windows CE。?
3.3、Compactness:?
SQLite是被設(shè)計成輕量級,自包含的。one header file, one library, and you’re relational, no external database server required?
3.4、簡單(Simplicity)、靈活(Flexibility)、可靠(Reliability):?
SQLite的核心大約有3萬行標(biāo)準(zhǔn)C代碼,這些代碼都是模塊化的,很容易閱讀。?
SQLite由以下幾個部分組成:SQL編譯器、內(nèi)核、后端以及附件。SQLite通過利用虛擬機(jī)和虛擬數(shù)據(jù)庫引擎(VDBE),是調(diào)試、修改和擴(kuò)展SQLite的內(nèi)核變得更加方便。所有SQL語句都被編譯成易讀的、可以在SQLite虛擬機(jī)中執(zhí)行的程序集。SQLite的整體結(jié)構(gòu)圖如下:?
? ? ? ? ? ? ? ?
值得一提的是,袖珍型的SQLite竟然可以支持高達(dá)2TB大小的數(shù)據(jù)庫,每個數(shù)據(jù)庫都是以單個文件的形式存在,這些數(shù)據(jù)都是以B-Tree的數(shù)據(jù)結(jié)構(gòu)形式存儲在磁盤上。?
在事務(wù)處理方面,SQLite通過數(shù)據(jù)庫級上的獨占性和共享鎖來實現(xiàn)獨立事務(wù)處理。這意味著多個進(jìn)程可以在同一時間從同一數(shù)據(jù)庫讀取數(shù)據(jù),但只有一個可以寫入數(shù)據(jù)。在某個進(jìn)程或線程想數(shù)據(jù)庫執(zhí)行寫操作之前,必須獲得獨占鎖。在獲得獨占鎖之后,其他的讀或?qū)懖僮鲗⒉粫侔l(fā)生。
4.數(shù)據(jù)類型?
SQLite為弱類型數(shù)據(jù)。?
SQLite采用動態(tài)數(shù)據(jù)類型,當(dāng)某個值插入到數(shù)據(jù)庫時,SQLite將會檢查它的類型,如果該類型與關(guān)聯(lián)的列不匹配,SQLite則會嘗試將該值轉(zhuǎn)換成該列的類型,如果不能轉(zhuǎn)換,則該值將作為本身的類型存儲,SQLite稱這為“弱類型”。但有一個特例,如果是INTEGER PRIMARY KEY,則其他類型不會被轉(zhuǎn)換,會報一個“datatype missmatch”的錯誤。因為定義為INTEGER PRIMARY KEY的字段只能存儲64位整數(shù), 當(dāng)向這種字段保存除整數(shù)以外的數(shù)據(jù)時,將會產(chǎn)生錯誤。 ?
概括來講,SQLite支持NULL、INTEGER、REAL、TEXT和BLOB數(shù)據(jù)類型,分別代表空值、整型值、浮點值、字符串文本、二進(jìn)制對象。?
一般數(shù)據(jù)采用的固定的靜態(tài)數(shù)據(jù)類型,而SQLite采用的是動態(tài)數(shù)據(jù)類型,會根據(jù)存入值自動判斷。SQLite具有以下五種常用的數(shù)據(jù)類型:
NULL: 這個值為空值?
VARCHAR(n):長度不固定且其最大長度為 n 的字串,n不能超過 4000。?
CHAR(n):長度固定為n的字串,n不能超過 254。?
INTEGER: 值被標(biāo)識為整數(shù),依據(jù)值的大小可以依次被存儲為1,2,3,4,5,6,7,8.?
REAL: 所有值都是浮動的數(shù)值,被存儲為8字節(jié)的IEEE浮動標(biāo)記序號.?
TEXT: 值為文本字符串,使用數(shù)據(jù)庫編碼存儲(TUTF-8, UTF-16BE or UTF-16-LE).?
BLOB: 值是BLOB數(shù)據(jù)塊,以輸入的數(shù)據(jù)格式進(jìn)行存儲。如何輸入就如何存儲,不改 ?變格式。?
DATA :包含了 年份、月份、日期。?
TIME: 包含了 小時、分鐘、秒。
二、數(shù)據(jù)庫使用
SQLiteOpenHelper數(shù)據(jù)庫版本管理?
為了實現(xiàn)對數(shù)據(jù)庫版本進(jìn)行管理,SQLiteOpenHelper類提供了兩個重要的方法,分別是
onCreate(SQLiteDatabase db)
onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion),123
前者用于初次使用軟件時生成數(shù)據(jù)庫表,后者用于升級軟件時更新數(shù)據(jù)庫表結(jié)構(gòu)。
當(dāng)調(diào)用SQLiteOpenHelper的getWritableDatabase()或者getReadableDatabase()方法獲取用于操作數(shù)據(jù)庫的SQLiteDatabase實例的時候,如果數(shù)據(jù)庫不存在,Android系統(tǒng)會自動生成一個數(shù)據(jù)庫,接著調(diào)用onCreate()方法,onCreate()方法在初次生成數(shù)據(jù)庫時才會被調(diào)用,在onCreate()方法里可以生成數(shù)據(jù)庫表結(jié)構(gòu)及添加一些應(yīng)用使用到的初始化數(shù)據(jù)。onUpgrade()方法在數(shù)據(jù)庫的版本發(fā)生變化時會被調(diào)用,一般在軟件升級時才需改變版本號,而數(shù)據(jù)庫的版本是由程序員控制的,假設(shè)數(shù)據(jù)庫現(xiàn)在的版本是1,由于業(yè)務(wù)的變更,修改了數(shù)據(jù)庫表結(jié)構(gòu),這時候就需要升級軟件,升級軟件時希望更新用戶手機(jī)里的數(shù)據(jù)庫表結(jié)構(gòu),為了實現(xiàn)這一目的,可以把原來的數(shù)據(jù)庫版本設(shè)置為2(有同學(xué)問設(shè)置為3行不行?當(dāng)然可以,如果你愿意,設(shè)置為100也行),并且在?
onUpgrade()方法里面實現(xiàn)表結(jié)構(gòu)的更新。當(dāng)軟件的版本升級次數(shù)比較多,這時在onUpgrade()方法里面可以根據(jù)原版號和目標(biāo)版本號進(jìn)行判斷,然后作出相應(yīng)的表結(jié)構(gòu)及數(shù)據(jù)更新。?
? getWritableDatabase()和getReadableDatabase()方法都可以獲取一個用于操作數(shù)據(jù)庫的SQLiteDatabase實例。但getWritableDatabase() 方法以讀寫方式打開數(shù)據(jù)庫,一旦數(shù)據(jù)庫的磁盤空間滿了,數(shù)據(jù)庫就只能讀而不能寫,倘若使用getWritableDatabase()打開數(shù)據(jù)庫就會出錯。?
getReadableDatabase()方法先以讀寫方式打開數(shù)據(jù)庫,如果數(shù)據(jù)庫的磁盤空間滿了,就會打開失敗,當(dāng)打開失敗后會繼續(xù)嘗試以只讀方式打開數(shù)據(jù)庫。
?
public class DatabaseHelper extends SQLiteOpenHelper { ?
? ? ? ? //類沒有實例化,是不能用作父類構(gòu)造器的參數(shù),必須聲明為靜態(tài) ?
? ? ? ? ?private static final String name = "count"; //數(shù)據(jù)庫名稱 ?
? ? ? ? ?private static final int version = 1; //數(shù)據(jù)庫版本 ?更新之后改變數(shù)據(jù)庫版本號
? ? ? ? ?public DatabaseHelper(Context context) { ?
? ? ? ? ? ? ? //第三個參數(shù)CursorFactory指定在執(zhí)行查詢時獲得一個游標(biāo)實例的工廠類,設(shè)置為null,代表使用系統(tǒng)默認(rèn)的工廠類 ?
? ? ? ? ? ? ? ? super(context, name, null, version); ?
? ? ? ? ?} ? ?
? ? ? ? @Override ?
? ? ? ? public void onCreate(SQLiteDatabase db) { ?
? ? ? ? ? ? ? db.execSQL("CREATE TABLE IF NOT EXISTS person (personid integer primary key autoincrement, name varchar(20), age?
INTEGER)"); ? ? ??
? ? ? ? ?} ??
? ? ? ? @Override ??
? ? ? ? public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { ?
? ? ? ? ? ? ? ? ?db.execSQL("ALTER TABLE person ADD phone VARCHAR(12)"); //往表中增加一列 ? ?
? ? ? ? ?} ?123456789101112131415161718192021
將會對比版本號,如果本身沒有數(shù)據(jù)庫,即數(shù)據(jù)庫版本號為0,也就是第一次安裝app,就會直接走onCreate方法,如果數(shù)據(jù)庫本身已經(jīng)存在了,如果版本號大于改版本號,就會執(zhí)行onUpgrade方法。數(shù)據(jù)庫版本只能升級,不能降級,降級會閃退。
三、基本語句:
openOrCreateDatabase(String path,SQLiteDatabase.CursorFactory ?factory)?
打開或創(chuàng)建數(shù)據(jù)庫?
insert(String table,String nullColumnHack,ContentValues ?values)?
插入一條記錄?
delete(String table,String whereClause,String[] ?whereArgs)?
刪除一條記錄?
query(String table,String[] columns,String selection,String[] ?selectionArgs,String groupBy,String having,String ?orderBy)?
查詢一條記錄?
update(String table,ContentValues values,String whereClause,String[] ?whereArgs)?
修改記錄?
execSQL(String sql)?
執(zhí)行一條SQL語句?
close()?
關(guān)閉數(shù)據(jù)庫
1、建表語句:
?
CREATE TABLE person (personid integer primary key autoincrement, name varchar(20),age integer default(0); 1
主鍵自增,最高20位,default默認(rèn)值。
2、插入
?
insert into person(name, age) values(‘小明’,3) ?1
3、刪除
?
delete from person ?where age=10;1
4、更新
?
update person set name=‘小明‘ where age=10 ?1
5、查詢
?
select * from person ? ? ? 查詢所有
select * from person order by id desc ? ?降序查詢,asc是升序
select name from person group by name having count(*)>1 ? ?分組查詢?
select * from Account limit 5 offset 3 ? ? ? ? 分頁查詢 ? ?123456
6、對表進(jìn)行操作alert
?
增加一列: alert(into) person add address varchar(255);
刪除列: alert person drop column age;
重命名列: alert person change age age_number integer;
**四、實例用法:**
寫法,傳統(tǒng)的一般的sql語句和insert方法,除了用execSQL()之外,還有
insert()、delete()、update()和query() ?能完成數(shù)據(jù)的添加、刪除、更新、查詢操作。
1、插入
(1)
SQLiteDatabase db = ....; ??
db.execSQL("insert into person(name, age) values(?,?)", new Object[]{"炸死特", 4}); ? ??
db.close(); ?
execSQL(String sql, Object[] bindArgs)方法的第一個參數(shù)為SQL語句,第二個參數(shù)為SQL語句中占位符參數(shù)的值,參數(shù)值在數(shù)組中的順序要和占位符的位置對應(yīng)。
用占位符可以省去轉(zhuǎn)義的痛苦。以免里面參數(shù)多次進(jìn)行轉(zhuǎn)義。
(2)
Insert()方法用于添加數(shù)據(jù),各個字段的數(shù)據(jù)使用ContentValues進(jìn)行存放,ContentValues類似于map集合,它提供了存取數(shù)據(jù)對應(yīng)的put(String key, Xxx value)和getAsXxx(String key)方法, ?key為字段名稱,value為字段值,Xxx指的是各種常用的數(shù)據(jù)類型,如:String、Integer等。
SQLiteDatabase db = databaseHelper.getWritableDatabase(); ? ?
ContentValues values = new ContentValues(); ? ?
values.put("name", "炸死特"); ? ?
values.put("age", 4); ? ?
long rowid = db.insert(“person”, null, values);//返回新添記錄的行號,與主鍵id無關(guān) ?
2、查詢:1234567891011121314151617181920212223242526272829
(1)?
SQLiteDatabase db = ….;?
Cursor cursor = db.rawQuery(“select * from person where name like ? and age=?”, new String[]{“%炸死特%”, “4”});?
while (cursor.moveToNext()) {?
? int personid = cursor.getInt(0); //獲取第一列的值,第一列的索引從0開始?
? String name = cursor.getString(1);//獲取第二列的值?
? int age = cursor.getInt(2);//獲取第三列的值?
}?
cursor.close();?
db.close(); ?
?
Cursor是結(jié)果集游標(biāo),用于對結(jié)果集進(jìn)行隨機(jī)訪問,如果大家熟悉jdbc, 其實Cursor與JDBC中的ResultSet作用很相似。使用moveToNext()方法可以將游標(biāo)從當(dāng)前行移動到下一行,如果已經(jīng)移過了結(jié)果集的最后一行,返回結(jié)果為false,否則為true。另外Cursor 還有常用的moveToPrevious()方法(用于將游標(biāo)從當(dāng)前行移動到上一行,如果已經(jīng)移過了結(jié)果集的第一行,返回值為false,否則為true )、moveToFirst()方法(用于將游標(biāo)移動到結(jié)果集的第一行,如果結(jié)果集為空,返回值為false,否則為true )和moveToLast()方法(用于將游標(biāo)移動到結(jié)果集的最后一行,如果結(jié)果集為空,返回值為false,否則為true ) 。
(2)
SQLiteDatabase db = databaseHelper.getWritableDatabase(); ? ?
Cursor cursor = db.query("person", new String[]{"personid,name,age"}, "name like ?", new String[]{"%炸死特%"}, null, null, "personid ?desc", "1,2"); ?
while (cursor.moveToNext()) { ?
? ? ? ? ?int personid = cursor.getInt(0); //獲取第一列的值,第一列的索引從0開始 ??
? ? ? ? ? String name = cursor.getString(1);//獲取第二列的值 ?
? ? ? ? ? int age = cursor.getInt(2);//獲取第三列的值 ??
} ??
cursor.close(); ?
db.close(); ? ? ??
query參數(shù),
query(table, columns, selection, selectionArgs, groupBy, having, orderBy, limit)方法各
**參數(shù)的含義:**
table:表名。相當(dāng)于select語句from關(guān)鍵字后面的部分。如果是多表聯(lián)合查詢,可以用逗號將兩個表名分開。
columns:要查詢出來的列名。相當(dāng)于select語句select關(guān)鍵字后面的部分。
selection:查詢條件子句,相當(dāng)于select語句where關(guān)鍵字后面的部分,在條件子句允許使用占位符“?”
selectionArgs:對應(yīng)于selection語句中占位符的值,值在數(shù)組中的位置與占位符在語句中的位置必須一致,否則就會有異常。
groupBy:相當(dāng)于select語句group by關(guān)鍵字后面的部分
having:相當(dāng)于select語句having關(guān)鍵字后面的部分
orderBy:相當(dāng)于select語句order by關(guān)鍵字后面的部分,如:personid desc, age asc;
limit:指定偏移量和獲取的記錄數(shù),相當(dāng)于select語句limit關(guān)鍵字后面的部分。
3.刪除
(1)DELETE FROM table_name
或者:
DELETE * FROM table_name
? ? ?當(dāng)然要加上條件判斷,
? ?SQLiteDatabase db = databaseHelper.getWritableDatabase(); ?
? db.execSQL("delete from ?table person where age >2 "); ?
? db.close(); ?
(2)
SQLiteDatabase db = databaseHelper.getWritableDatabase(); ?
db.delete("person", "personid<?", new String[]{"2"}); ?
db.close(); ?
上面代碼用于從person表中刪除personid小于2的記錄。
第一個是表名,第二個參數(shù)是條件,相當(dāng)于where personid< ? ?,?是占位符,內(nèi)容是第三個參數(shù)。
5.update()方法
(1)123456789101112131415161718192021222324252627282930313233343536373839404142
SQLiteDatabase db = databaseHelper.getWritableDatabase();?
?db.execSQL(“update person set name=’呵呵’ where personid=1”);?
?db.close();?
“`?
(2)?
SQLiteDatabase db = databaseHelper.getWritableDatabase();?
ContentValues values = new ContentValues();?
?values.put(“name”, “呵呵”);//key為字段名,value為值?
db.update(“person”, values, “personid=?”, new String[]{“1”});?
db.close(); ?
上面代碼用于把person表中personid等于1的記錄的name字段的值改為“呵呵”。
---------------------?
原文:https://blog.csdn.net/qq_37237245/article/details/72677163?
版權(quán)聲明:本文為博主原創(chuàng)文章,轉(zhuǎn)載請附上博文鏈接!
總結(jié)
以上是生活随笔為你收集整理的SQLlite在安卓中的基本详解和简单使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 块编码、对象编码、小波编码、分布式编码【
- 下一篇: android开发中的数据库SQLite