1. 程式人生 > >SQLlite在安卓中的基本詳解和簡單使用

SQLlite在安卓中的基本詳解和簡單使用

一、基礎介紹

1.SQLite 是一個程序內的庫,是一種輕量級的、自給自足的、無伺服器的、無需配置的,事務性的SQL資料庫引擎.和他其他的資料庫一樣,SQLite引擎不是一個獨立的程序,可以按應用程式需求進行靜態或動態連線。SQLite可以直接訪問其儲存檔案。

SQLite是一個開源的嵌入式關係資料庫,它在2000年由D. Richard Hipp釋出,用C語言編寫的開源嵌入式資料庫引擎,它的減少應用程式管理資料的開銷,SQLite可移植性好,很容易使用,很小,高效而且可靠。它支援大多數的SQL92標準,並且可以在所有主要的作業系統上執行。

SQLite嵌入到使用它的應用程式中,它們共用相同的程序空間,而不是單獨的一個程序。從外部看,它並不像一個RDBMS,但在程序內部,它卻是完整的,自包含的資料庫引擎。嵌入式資料庫的一大好處就是在你的程式內部不需要網路配置,也不需要管理。因為客戶端和伺服器在同一程序空間執行。

SQLite 的資料庫許可權只依賴於檔案系統,沒有使用者帳戶的概念。SQLite 有資料庫級鎖定,沒有網路伺服器。它需要的記憶體,其它開銷很小,適合用於嵌入式裝置。你需要做的僅僅是把它正確的編譯到你的程式。

2.SQLite 是一個開源的嵌入式關係資料庫。 其特點是高度便攜、使用方便、結構緊湊、高效、可靠。 與其他資料庫管理系統不同,SQLite 的安裝和執行非常簡單,在大多數情況下 - 只要確保SQLite的二進位制檔案存在即可開始建立、連線和使用資料庫。如果您正在尋找一個嵌入式資料庫專案或解決方案,SQLite是絕對值得考慮。

3、SQLite的特點(SQLite’s Features and Philosophy)
3.1、零配置(Zero Configuration)
3.2、可移植(Portability):
它是執行在Windows,Linux,BSD,Mac OS X和一些商用Unix系統,比如Sun的Solaris,IBM的AIX,同樣,它也可以工作在許多嵌入式作業系統下,比如QNX,VxWorks,Palm OS, Symbin和Windows CE。
3.3、Compactness:
SQLite是被設計成輕量級,自包含的。one header file, one library, and you’re relational, no external database server required
3.4、簡單(Simplicity)、靈活(Flexibility)、可靠(Reliability):
SQLite的核心大約有3萬行標準C程式碼,這些程式碼都是模組化的,很容易閱讀。
SQLite由以下幾個部分組成:SQL編譯器、核心、後端以及附件。SQLite通過利用虛擬機器和虛擬資料庫引擎(VDBE),是除錯、修改和擴充套件SQLite的核心變得更加方便。所有SQL語句都被編譯成易讀的、可以在SQLite虛擬機器中執行的程式集。SQLite的整體結構圖如下:
這裡寫圖片描述

值得一提的是,袖珍型的SQLite竟然可以支援高達2TB大小的資料庫,每個資料庫都是以單個檔案的形式存在,這些資料都是以B-Tree的資料結構形式儲存在磁碟上。
在事務處理方面,SQLite通過資料庫級上的獨佔性和共享鎖來實現獨立事務處理。這意味著多個程序可以在同一時間從同一資料庫讀取資料,但只有一個可以寫入資料。在某個程序或執行緒想資料庫執行寫操作之前,必須獲得獨佔鎖。在獲得獨佔鎖之後,其他的讀或寫操作將不會再發生。

4.資料型別
SQLite為弱型別資料。
SQLite採用動態資料型別,當某個值插入到資料庫時,SQLite將會檢查它的型別,如果該型別與關聯的列不匹配,SQLite則會嘗試將該值轉換成該列的型別,如果不能轉換,則該值將作為本身的型別儲存,SQLite稱這為“弱型別”。但有一個特例,如果是INTEGER PRIMARY KEY,則其他型別不會被轉換,會報一個“datatype missmatch”的錯誤。因為定義為INTEGER PRIMARY KEY的欄位只能儲存64位整數, 當向這種欄位儲存除整數以外的資料時,將會產生錯誤。
概括來講,SQLite支援NULL、INTEGER、REAL、TEXT和BLOB資料型別,分別代表空值、整型值、浮點值、字串文字、二進位制物件。
一般資料採用的固定的靜態資料型別,而SQLite採用的是動態資料型別,會根據存入值自動判斷。SQLite具有以下五種常用的資料型別:

NULL: 這個值為空值
VARCHAR(n):長度不固定且其最大長度為 n 的字串,n不能超過 4000。
CHAR(n):長度固定為n的字串,n不能超過 254。
INTEGER: 值被標識為整數,依據值的大小可以依次被儲存為1,2,3,4,5,6,7,8.
REAL: 所有值都是浮動的數值,被儲存為8位元組的IEEE浮動標記序號.
TEXT: 值為文字字串,使用資料庫編碼儲存(TUTF-8, UTF-16BE or UTF-16-LE).
BLOB: 值是BLOB資料塊,以輸入的資料格式進行儲存。如何輸入就如何儲存,不改 變格式。
DATA :包含了 年份、月份、日期。
TIME: 包含了 小時、分鐘、秒。

二、資料庫使用

SQLiteOpenHelper資料庫版本管理
為了實現對資料庫版本進行管理,SQLiteOpenHelper類提供了兩個重要的方法,分別是

onCreate(SQLiteDatabase db)

onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)

前者用於初次使用軟體時生成資料庫表,後者用於升級軟體時更新資料庫表結構。

當呼叫SQLiteOpenHelper的getWritableDatabase()或者getReadableDatabase()方法獲取用於操作資料庫的SQLiteDatabase例項的時候,如果資料庫不存在,Android系統會自動生成一個數據庫,接著呼叫onCreate()方法,onCreate()方法在初次生成資料庫時才會被呼叫,在onCreate()方法裡可以生成資料庫表結構及新增一些應用使用到的初始化資料。onUpgrade()方法在資料庫的版本發生變化時會被呼叫,一般在軟體升級時才需改變版本號,而資料庫的版本是由程式設計師控制的,假設資料庫現在的版本是1,由於業務的變更,修改了資料庫表結構,這時候就需要升級軟體,升級軟體時希望更新使用者手機裡的資料庫表結構,為了實現這一目的,可以把原來的資料庫版本設定為2(有同學問設定為3行不行?當然可以,如果你願意,設定為100也行),並且在
onUpgrade()方法裡面實現表結構的更新。當軟體的版本升級次數比較多,這時在onUpgrade()方法裡面可以根據原版號和目標版本號進行判斷,然後作出相應的表結構及資料更新。
getWritableDatabase()和getReadableDatabase()方法都可以獲取一個用於操作資料庫的SQLiteDatabase例項。但getWritableDatabase() 方法以讀寫方式開啟資料庫,一旦資料庫的磁碟空間滿了,資料庫就只能讀而不能寫,倘若使用getWritableDatabase()開啟資料庫就會出錯。
getReadableDatabase()方法先以讀寫方式開啟資料庫,如果資料庫的磁碟空間滿了,就會開啟失敗,當開啟失敗後會繼續嘗試以只讀方式開啟資料庫。

public class DatabaseHelper extends SQLiteOpenHelper {  

        //類沒有例項化,是不能用作父類構造器的引數,必須宣告為靜態  

         private static final String name = "count"; //資料庫名稱  

         private static final int version = 1; //資料庫版本  更新之後改變資料庫版本號
         public DatabaseHelper(Context context) {  
              //第三個引數CursorFactory指定在執行查詢時獲得一個遊標例項的工廠類,設定為null,代表使用系統預設的工廠類  
                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)"); //往表中增加一列    
         }  

將會對比版本號,如果本身沒有資料庫,即資料庫版本號為0,也就是第一次安裝app,就會直接走onCreate方法,如果資料庫本身已經存在了,如果版本號大於改版本號,就會執行onUpgrade方法。資料庫版本只能升級,不能降級,降級會閃退。

三、基本語句:

openOrCreateDatabase(String path,SQLiteDatabase.CursorFactory factory)
開啟或建立資料庫
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)
執行一條SQL語句
close()
關閉資料庫

1、建表語句:

CREATE TABLE person (personid integer primary key autoincrement, name varchar(20),age integer default(0); 

主鍵自增,最高20位,default預設值。

2、插入

insert into person(name, age) values(‘小明’,3)  

3、刪除

delete from person  where age=10;

4、更新

update person set name=‘小明‘ where age=10  

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         分頁查詢    

6、對錶進行操作alert

增加一列: alert(into) person add address varchar(255);

刪除列: alert person drop column age;

重新命名列: alert person change age age_number integer;

**四、例項用法:**

寫法,傳統的一般的sql語句和insert方法,除了用execSQL()之外,還有
insert()、delete()、update()和query()  能完成資料的新增、刪除、更新、查詢操作。

1、插入
(1)
SQLiteDatabase db = ....;   
db.execSQL("insert into person(name, age) values(?,?)", new Object[]{"炸死特", 4});     
db.close();  

execSQL(String sql, Object[] bindArgs)方法的第一個引數為SQL語句,第二個引數為SQL語句中佔位符引數的值,引數值在陣列中的順序要和佔位符的位置對應。
用佔位符可以省去轉義的痛苦。以免裡面引數多次進行轉義。
(2)
Insert()方法用於新增資料,各個欄位的資料使用ContentValues進行存放,ContentValues類似於map集合,它提供了存取資料對應的put(String key, Xxx value)和getAsXxx(String key)方法,  key為欄位名稱,value為欄位值,Xxx指的是各種常用的資料型別,如: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無關  

2、查詢:

(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是結果集遊標,用於對結果集進行隨機訪問,如果大家熟悉jdbc, 其實Cursor與JDBC中的ResultSet作用很相似。使用moveToNext()方法可以將遊標從當前行移動到下一行,如果已經移過了結果集的最後一行,返回結果為false,否則為true。另外Cursor 還有常用的moveToPrevious()方法(用於將遊標從當前行移動到上一行,如果已經移過了結果集的第一行,返回值為false,否則為true )、moveToFirst()方法(用於將遊標移動到結果集的第一行,如果結果集為空,返回值為false,否則為true )和moveToLast()方法(用於將遊標移動到結果集的最後一行,如果結果集為空,返回值為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引數,
query(table, columns, selection, selectionArgs, groupBy, having, orderBy, limit)方法各

**引數的含義:**
table:表名。相當於select語句from關鍵字後面的部分。如果是多表聯合查詢,可以用逗號將兩個表名分開。
columns:要查詢出來的列名。相當於select語句select關鍵字後面的部分。
selection:查詢條件子句,相當於select語句where關鍵字後面的部分,在條件子句允許使用佔位符“?”
selectionArgs:對應於selection語句中佔位符的值,值在陣列中的位置與佔位符在語句中的位置必須一致,否則就會有異常。
groupBy:相當於select語句group by關鍵字後面的部分
having:相當於select語句having關鍵字後面的部分
orderBy:相當於select語句order by關鍵字後面的部分,如:personid desc, age asc;
limit:指定偏移量和獲取的記錄數,相當於select語句limit關鍵字後面的部分。
3.刪除
(1)DELETE FROM table_name
或者:
DELETE * FROM table_name
     當然要加上條件判斷,
   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的記錄。
第一個是表名,第二個引數是條件,相當於where personid<    ,?是佔位符,內容是第三個引數。
5.update()方法
(1)

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欄位的值改為“呵呵”。