天天看點

【移動開發】SQLite資料庫使用 資料類型小結

在我們平時做Android項目,不管是應用還是遊戲,都會用到SQLite資料庫,在這裡我還是簡單的整理了一下。

1.簡介

SQLite 是一個開源的嵌入式關系資料庫,實作自包容、零配置、支援事務的SQL資料庫引擎。 其特點是高度便攜、使用友善、結構緊湊、高效、可靠。 與其他資料庫管理系統不同,SQLite 的安裝和運作非常簡單,在大多數情況下 - 隻要確定SQLite的二進制檔案存在即可開始建立、連接配接和使用資料庫。如果您正在尋找一個嵌入式資料庫項目或解決方案,SQLite是絕對值得考慮。

一般的資料庫采用的是固定的靜态資料類型,SQLite采用動态資料類型,建立一個表時,可以在 CREATE TABLE 語句中指定某列的資料類型,但是你可以把任何資料類型放入任何列中。當某個值插入到資料庫時,SQLite将會檢查它的類型,如果該類型與關聯的列不比對,SQLite則會嘗試将該值轉換成該列的類型,如果不能轉換,則該值将作為本身的類型存儲,比如可以把一個字元串(String)放入 INTEGER 列。SQLite稱這為“弱類型”。但有一個特例,如果是INTEGER PRIMARY KEY,則其他類型不會被轉換,會報一個“datatype missmatch”的錯誤。

在事務處理方面,SQLite通過資料庫級上的獨占性和共享鎖來實作獨立事務處理。這意味着多個程序可以在同一時間從同一資料庫讀取資料,但隻有一個可以寫入資料。在某個程序或線程想資料庫執行寫操作之前,必須獲得獨占鎖。在獲得獨占鎖之後,其他的讀或寫操作将不會再發生。

此外,SQLite 不支援一些标準的 SQL 功能,特别是外鍵限制(FOREIGN KEY constrains),嵌套 transcaction 和 RIGHT OUTER JOIN 和 FULL OUTER JOIN, 還有一些 ALTER TABLE 功能。

除了上述功能外,SQLite 是一個完整的 SQL 系統,擁有完整的觸發器,交易等等。

2.Android 內建了 SQLite 資料庫

Android 在運作時(run-time)內建了 SQLite,是以每個 Android 應用程式都可以使用 SQLite 資料庫。對于熟悉 SQL 的開發人員來時,在 Android 開發中使用 SQLite 相當簡單。但是,由于 JDBC 會消耗太多的系統資源,是以 JDBC 對于手機這種記憶體受限裝置來說并不合适。是以,Android 提供了一些新的 API 來使用 SQLite 資料庫,Android 開發中,程式員需要學使用這些 API。

資料庫存儲在 data/data/<項目檔案夾>/databases/ 下。

A.資料類型

   1.NULL 空值

   2.INTEGER 帶符号的整型

   3.REAL 浮點型

   4.TEXT 字元串文本

   5.BLOB 二進制對象

但實際上,sqlite3也接受如下的資料類型:

   smallint 16 位元的整數。

   interger 32 位元的整數。

   decimal(p,s) p 精确值和 s 大小的十進位整數,精确值p是指全部有幾個數(digits)大小值,s是指小數點後有幾位數。如果沒有特别指定,則系統會設為 p=5; s=0 。

   float 32位元的實數。

   double 64位元的實數。

   char(n) n 長度的字串,n不能超過 254。

   varchar(n) 長度不固定且其最大長度為 n 的字串,n不能超過 4000。

   graphic(n) 和 char(n) 一樣,不過其機關是兩個字元 double-bytes, n不能超過127。這個形态是為了支援兩個字元長度的字型,例如中文字。

   vargraphic(n) 可變長度且其最大長度為 n 的雙字元字串,n不能超過 2000

   date 包含了 年份、月份、日期。

   time 包含了 小時、分鐘、秒。

   timestamp 包含了 年、月、日、時、分、秒、千分之一秒。

   datetime 包含日期時間格式,必須寫成'2010-08-05'不能寫為'2010-8-5',否則在讀取時會産生錯誤!

B.簡單使用

Android平台下資料庫相關類:

SQLiteOpenHelper 抽象類:通過從此類繼承實作使用者類,來提供資料庫打開、關閉等操作函數。

       SQLiteDatabase 資料庫通路類:執行對資料庫的插入記錄、查詢記錄等操作。

       SQLiteCursor 查詢結構操作類:用來通路查詢結果中的記錄。

Activites 可以通過 Content Provider 或者 Service 通路一個資料庫。

C.建立資料庫

Android不自動提供資料庫。在 Android 應用程式中使用 SQLite,必須自己建立資料庫,然後建立表、索引,填充資料。Android 提供了 SQLiteOpenHelper 幫助你建立一個資料庫,你隻要繼承 SQLiteOpenHelper 類,就可以輕松的建立資料庫。

SQLiteOpenHelper 類根據開發應用程式的需要,封裝了建立和更新資料庫使用的邏輯。SQLiteOpenHelper 的子類,至少需要實作三個方法:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

<code>package</code> <code>com.dandan.fm.db;</code>

<code>import</code> <code>android.content.Context;</code>

<code>import</code> <code>android.database.sqlite.SQLiteDatabase;</code>

<code>import</code> <code>android.database.sqlite.SQLiteDatabase.CursorFactory;</code>

<code>import</code> <code>android.database.sqlite.SQLiteOpenHelper;</code>

<code>/**</code>

<code> </code><code>* 可以通過SQLiteOpenHelper的以下兩個方法來或得SQLiteDatabase的對象:</code>

<code> </code><code>* getReadableDatabase() 建立或者打開一個查詢資料庫</code>

<code> </code><code>* getWritableDatabase() 建立或者打開一個可寫資料庫</code>

<code> </code><code>*/</code>

<code>public</code> <code>class</code> <code>DBHelper </code><code>extends</code> <code>SQLiteOpenHelper {</code>

<code>    </code><code>/**</code>

<code>     </code><code>* 構造函數,必須實作</code>

<code>     </code><code>* @param context 上下文路徑</code>

<code>     </code><code>* @param name 資料庫名稱</code>

<code>     </code><code>* @param factory 可選遊标工廠,通常為NULL</code>

<code>     </code><code>* @param version 目前資料庫版本号</code>

<code>     </code><code>*/</code>

<code>    </code><code>public</code> <code>DBHelper(Context context, </code><code>String</code> <code>name, CursorFactory factory,</code><code>int</code> <code>version) {</code>

<code>        </code><code>super</code><code>(context, name, factory, version);</code>

<code>    </code><code>}</code>

<code>                                                                                                                                                                                                                                                                                                                        </code> 

<code>    </code><code>//資料庫第一次建立時會調用,一般在其中建立資料庫表</code>

<code>    </code><code>@Override</code>

<code>    </code><code>public</code> <code>void</code> <code>onCreate(SQLiteDatabase db) {</code>

<code>        </code><code>//使用execSQL()方法執行DDL語句,如果沒有異常,這個方法沒有傳回值</code>

<code>        </code><code>db.execSQL(</code><code>"create table user(id INTEGER PRIMARY KEY AUTOINCREMENT,"</code> <code>+ </code><code>"name varchar(20), address TEXT)"</code><code>);</code>

<code>    </code><code>//當資料庫需要修改的時候,Android系統會主動的調用這個方法。</code>

<code>    </code><code>public</code> <code>void</code> <code>onUpgrade(SQLiteDatabase db, </code><code>int</code> <code>oldVersion, </code><code>int</code> <code>newVersion) {</code>

<code>    </code><code>//資料庫版本更新時,更新資料庫操作</code>

<code>    </code><code>//打開資料庫時的回調函數,一般不會用</code>

<code>    </code><code>public</code> <code>void</code> <code>onOpen(SQLiteDatabase db) {</code>

<code>        </code><code>super</code><code>.onOpen(db);</code>

<code>    </code><code>public</code> <code>synchronized </code><code>void</code> <code>close() {</code>

<code>        </code><code>super</code><code>.close();</code>

<code>}</code>

說明:

建立表和索引

<code>db.execSQL(</code><code>"create table user(id INTEGER PRIMARY KEY AUTOINCREMENT,"</code> <code>+</code>

<code> </code><code>"name varchar(20), address TEXT)"</code><code>);</code>

給表添加資料

 有兩種方式添加資料:

       1.向上面建立表一樣,可以使用execSQL方法執行 INSERT, UPDATE, DELETE 等語句來更新表的資料。execSQL适用于        所有不需要傳回結果的SQL語句。如:

<code>db.execSQL(</code><code>"INSERT INTO user (name, address) VALUES ('woniu',"</code> <code>+</code>

<code>"'http://http://smallwoniu.blog.51cto.com/')"</code><code>);</code>

2.SQLiteDatabase 對象的 insert(), update(), delete() 方法。這些方法把 SQL 語句的一部分作為參數。如:

<code>private</code> <code>SQLiteDatabase mDataBase = </code><code>null</code><code>;</code>

<code>private</code> <code>static</code> <code>final</code> <code>String</code> <code>USER_TABLE = </code><code>"user"</code><code>;</code>

<code>                                                                                                                                                                                                </code> 

<code>public</code> <code>void</code> <code>getDB() {</code>

<code>    </code><code>//建立DBHelper對象</code>

<code>    </code><code>DBHelper db = </code><code>new</code> <code>DBHelper(</code><code>this</code><code>, USER_TABLE, </code><code>null</code><code>, </code><code>1</code><code>);</code>

<code>    </code><code>//擷取可寫SQLiteDatabase</code>

<code>    </code><code>mDataBase = db.getWritableDatabase();</code>

<code>public</code> <code>void</code> <code>insert() {</code>

<code>    </code><code>//ContentValues對象,向其中插入鍵值對,鍵是資料庫列名,值是插入到這一列的值</code>

<code>    </code><code>ContentValues cv = </code><code>new</code> <code>ContentValues();</code>

<code>    </code><code>cv.put(</code><code>"name"</code><code>, </code><code>"LiuMing"</code><code>);</code>

<code>    </code><code>cv.put(</code><code>"address"</code><code>, </code><code>"ShangHai"</code><code>);</code>

<code>    </code><code>mDataBase.insert(USER_TABLE, </code><code>null</code><code>, cv);</code>

<code>public</code> <code>int</code> <code>update() {</code>

<code>    </code><code>cv.put(</code><code>"name"</code><code>, </code><code>"MaLi"</code><code>);</code>

<code>    </code><code>//第三個參數where語句,相當于sql語句中where後面的語句,?是占位符</code>

<code>    </code><code>//第四個參數是占位符的值</code>

<code>    </code><code>return</code> <code>mDataBase.update(USER_TABLE, cv, </code><code>"id = ?"</code><code>, </code><code>new</code> <code>String</code><code>[]{</code><code>"1"</code><code>});</code>

<code>public</code> <code>int</code> <code>delete</code><code>() {</code>

<code>    </code><code>//和udate()類似</code>

<code>    </code><code>return</code> <code>mDataBase.</code><code>delete</code><code>(USER_TABLE, </code><code>"id = ? and name = ?"</code><code>,</code>

<code>        </code><code>new</code> <code>String</code><code>[]{</code><code>"1"</code><code>, </code><code>"MaLi"</code><code>});</code>

查詢資料庫

       與INSERT,UPDATE,DELETE類似,有兩種方法從資料庫中查詢資料。

<code> </code><code>* 使用rawQuery()直接調用SELECT語句,最簡單的查詢方法</code>

<code> </code><code>* 如果查詢是動态的,使用rawQuery就會非常複雜</code>

<code> </code><code>* @return Cursor可以疊代查詢結果</code>

<code>public</code> <code>Cursor rawQuery() {</code>

<code>    </code><code>return</code> <code>mDataBase.rawQuery(</code><code>"select * from user where id = ? and name = ?"</code><code>, </code><code>new</code> <code>String</code><code>[]{</code><code>"1"</code><code>, </code><code>"LiuMing"</code><code>});</code>

<code>//使用SELECT語句段建構查詢,SELECT語句内容做為query()方法的參數</code>

<code>public</code> <code>Cursor query() {</code>

<code>    </code><code>String</code><code>[] columns = {</code><code>"name"</code><code>, </code><code>"address"</code><code>};</code>

<code>    </code><code>//第二個參數: 要查詢的列名</code>

<code>    </code><code>//第三個參數:where語句</code>

<code>    </code><code>//第三個參數:where語句中占位符的值</code>

<code>    </code><code>//第四個參數:對查詢結果進行分組</code>

<code>    </code><code>//第五個參數:對分組結果進行限制</code>

<code>    </code><code>//第六個參數:對查詢結果進行排序</code>

<code>    </code><code>return</code> <code>mDataBase.query(USER_TABLE, columns, </code><code>"id = ?"</code><code>, </code><code>new</code> <code>String</code><code>[] {</code><code>"1"</code><code>},</code><code>null</code><code>, </code><code>null</code><code>, </code><code>null</code><code>);</code>

   最後着重提及一下使用遊标,不管如何執行查詢,都會傳回一個Cursor,Curosr主要方法如下:

getCount():

獲得結果集中有多少記錄。

moveToFirst():

移動到第一行。

moveToNext():

移動到下一行,可周遊所有記錄。

isAfterLast():

判斷是否最後一行。

getColumnNames():

傳回字段名。

getColumnCount():

傳回字段号。

getString(),getInt():

得到給定字段目前記錄的值。

requery():

重新執行查詢得到遊标。

close():

釋放遊标資源。

<code>/** 查詢記事本表的所有記錄 **/</code>

<code>    </code><code>public</code> <code>ArrayList&lt;HashMap&lt;</code><code>String</code><code>, </code><code>Object</code><code>&gt;&gt; getWriteAllCount() {</code>

<code>        </code><code>// 打開資料庫</code>

<code>        </code><code>openDatabase();</code>

<code>        </code><code>ArrayList&lt;HashMap&lt;</code><code>String</code><code>, </code><code>Object</code><code>&gt;&gt; data = </code><code>null</code><code>; </code><code>// 接收資料</code>

<code>        </code><code>// Cursor----ResultSet:用于接收資料庫資料清單</code>

<code>        </code><code>Cursor cursor = db.query(DBInfo.Table.TB_WRITE_NAME, </code><code>null</code><code>, </code><code>null</code><code>, </code><code>null</code><code>,</code><code>null</code><code>, </code><code>null</code><code>, </code><code>null</code><code>);</code>

<code>        </code><code>if</code> <code>(</code><code>null</code> <code>!= cursor &amp;&amp; cursor.getCount() &gt; </code><code>0</code><code>) {</code>

<code>            </code><code>data = </code><code>new</code> <code>ArrayList&lt;HashMap&lt;</code><code>String</code><code>, </code><code>Object</code><code>&gt;&gt;();</code>

<code>            </code><code>while</code> <code>(cursor.moveToNext()) {</code>

<code>                </code><code>HashMap&lt;</code><code>String</code><code>, </code><code>Object</code><code>&gt; map = </code><code>new</code> <code>HashMap&lt;</code><code>String</code><code>, </code><code>Object</code><code>&gt;();</code>

<code>                </code><code>map.put(</code><code>"title"</code><code>,cursor.getString(cursor.getColumnIndex(</code><code>"title"</code><code>)));</code>

<code>                </code><code>map.put(</code><code>"content"</code><code>,cursor.getString(cursor.getColumnIndex(</code><code>"content"</code><code>)));</code>

<code>                </code><code>map.put(</code><code>"imagePath"</code><code>,cursor.getString(cursor.getColumnIndex(</code><code>"imagePath"</code><code>)));</code>

<code>                </code><code>map.put(</code><code>"time"</code><code>, cursor.getString(cursor.getColumnIndex(</code><code>"time"</code><code>)));</code>

<code>                </code><code>map.put(</code><code>"color"</code><code>,cursor.getString(cursor.getColumnIndex(</code><code>"color"</code><code>)));</code>

<code>                </code><code>map.put(</code><code>"background"</code><code>,cursor.getInt(cursor.getColumnIndex(</code><code>"background"</code><code>)));</code>

<code>                </code><code>map.put(</code><code>"lock"</code><code>,cursor.getInt(cursor.getColumnIndex(</code><code>"lock"</code><code>)));</code>

<code>                </code><code>data.add(map);</code>

<code>            </code><code>}</code>

<code>        </code><code>}</code>

<code>        </code><code>cursor.close();</code>

<code>        </code><code>db.close(); </code><code>// 用完記得要關閉哦</code>

<code>        </code><code>return</code> <code>data;</code>

當然,如果我們遇到大量反複對資料庫進行操作時,我們可以使用異步加載資料庫(可以看我的下一篇部落格),改善加的使用者體驗效果

<b>     本文轉自zhf651555765 51CTO部落格,原文連結:http://blog.51cto.com/smallwoniu/1249999</b><b>,如需轉載請自行聯系原作者</b>