1. 程式人生 > >嵌入式SQLite資料庫架構和設計

嵌入式SQLite資料庫架構和設計

SQLite是一個開源的、內嵌式的關係型資料庫。SQLite和Oracle和Access一樣是檔案型資料庫,就是說,一個數據庫就是一個檔案,此資料庫裡可以建立很多的表,可以建立索引、觸發器等等,但是它實際上得到的就是一個檔案。SQLite資料庫具有下面的特點:

  • (1)首先SQLite資料庫伺服器就在你的資料庫應用程式中,其好處是不需要網路配置和管理,也不需要通過設定資料來源訪問資料庫伺服器。

  • (2)其次SQLite資料庫的伺服器和客戶端執行在同一個程序中。這樣可以減少網路訪問的消耗,簡化資料庫管理,使你的程式部署起來更容易。

  • (3)再次SQLite在處理資料型別時與其它的資料庫不同。區別在於它所支援的型別以及這些型別是如何儲存、比較、強化(enforc)和指派(assign)。

SQLite的域完整性被稱為域親和性(affinity)。為了理解型別親和性,你必須先要理解儲存類和弱型別(manifesttyping)。SQLite有Integer、Real、Text、Blob和Null五個原始的資料型別,被稱為儲存類。儲存類這個詞表明瞭一個值在磁碟上儲存的格式,其實就是型別或資料型別的同義詞。

資料庫SQLite的資料庫架構

SQLite在架構上採用了模組的設計,它由公共介面、編譯器系統、虛擬機器和後端四個子系統組成。

1、介面(Interface)。由SQLite C API組成,也就是說不管是程式、指令碼語言還是庫檔案,最終都是通過它與SQLite互動的(我們通常用得較多的ODBC/JDBC最後也會轉化為相應C API的呼叫)。

2、編譯器(Compiler)。在編譯器中,分詞器(Tokenizer)和分析器(Parser)對SQL進行語法檢查,然後把它轉化為底層能更方便處理的分層的資料結構---語法樹,然後把語法樹傳給程式碼生成器(code generator)進行處理。而程式碼生成器根據它生成一種針對SQLite的彙編程式碼,最後由虛擬機器執行。

3、虛擬機器(Virtual Machine)。架構中最核心的部分是虛擬機器,或者叫做虛擬資料庫引擎(Virtual Database Engine,VDBE)。它和Java虛擬機器相似,解釋執行位元組程式碼。VDBE的位元組程式碼由128個操作碼(opcodes)構成,它們主要集中在資料庫操作。它的每一條指令都用來完成特定的資料庫操作(比如開啟一個表的遊標)或者為這些操作棧空間的準備(比如壓入引數)。

4、後端(Back-End)。後端由B-樹(B-tree),頁快取(page cache,pager)和作業系統介面(即系統呼叫)構成。B-tree和page cache共同對資料進行管理。B-tree的主要功能就是索引,它維護著各個頁面之間的複雜的關係,便於快速找到所需資料。而pager的主要作用就是通過OS介面在B-tree和Disk之間傳遞頁面。

嵌入式資料庫SQLite的資料型別

在SQLite資料庫中,不僅提供了儲存基本資料的功能,而且提供了對二進位制資料儲存的能力,這樣可以確保把採集到的農業影象資訊存放到資料庫中,由資料庫統一操作和管理,在SQLite資料庫中提供的基本資料型別不但可以進行轉化,還可以進行大小比較。資料型別如下:

  • (1)Integer整數值。有正負之分,它是由8個位元組(Bytes)表示。SQLite資料庫可以根據整數值的大小自動控制其所佔位元組的個數。

  • (2)Real實數型別。在SQLite由8個位元組來表示。

  • (3)Text文字字元資料型別。用來儲存文字資訊。SQLite資料庫支援多種字元編碼型別,包括UTF-8和UTF-16。字串的大小是沒有限制的。

  • (4)Blob二進位制資料物件型別。儲存二進位制資料,大小沒有限制。

  • (5)Null空型別。一個具有NULL儲存型別的值比所有其它型別值都小。SQLite資料庫對Null完全支援。

SQLite 資料庫本身一共有80多個API呼叫介面,功能簡單的資料庫程式用三個介面完成: sqlite3_open(),sqlite3_exec(), 和 sqlite3_close()。 要是想更好的控制資料庫引擎,使用sqlite3_prepare()函式把SQL語句編譯成位元組碼再通過sqlite3_step()函式來執行。在SQLite中,絕大多數介面提供了UTF-8和UTF-16兩個版本,大多數介面成對出現。

此外,SQLite資料庫中同時也提供了使用者對API介面擴充的機制。SQLite的擴充API用來支援使用者定義的函式、聚合和排序法。實現一個使用者自定義的函式分為兩步。首先,寫控制代碼。控制代碼實現一些你想通過SQL完成的功能。然後,註冊控制代碼。為它提供SQL名稱、引數的數量和一個指向控制代碼的指標。

資料庫控制和語句執行方式

從資料庫開啟開始,SQLite就要為sqlite3 *型別準備好記憶體,一直到資料庫關閉整個過程。開啟資料庫時,這個型別的變數指向你將操作的資料庫。SQLite資料庫和大多資料庫操作相同,其過程連線並開啟資料庫、處理事務和斷開連線並關閉資料庫構成:

1、連線並開啟資料庫。每個SQLite資料庫都儲存在單獨的作業系統檔案中,資料庫與檔案一一對應。連線並開啟資料庫的介面呼叫為sqlite3_open(),它用來開啟一個數據庫檔案,該資料庫檔案中可以包含許多個關係表。該介面呼叫成功返回SQLITE_OK。

資料庫開啟成功。SQLite還可以建立記憶體資料庫。如果你使用:memory:或一個空字串做資料庫名,資料庫將在RAM中建立。記憶體資料庫將只能被建立它的連線所存取,不能與其它連線共享。另外,記憶體資料庫只能存活於連線期間,一旦連線關閉,資料庫就將從記憶體中被刪除。

2、處理事務。SQLite 是支援事務處理的。預設情況下,事務自動提交,也就是每一個SQL語句都在一個獨立的事務下執行。任何SQL語句命令都在事務下執行。可以通過Begin、Commit和Rollback等命令手動提交事務。如開始、提交、回滾事務過程如下:

3、資料庫SQL語句執行。在SQLite資料庫中執行事務最常用的介面是sqlite3_exec(),在這個函式中有指向sqlite3_exec()的回撥函式的指標引數。例如做 insert 操作或做 delete 操作時,就沒有必要使用回撥,該函式指標可設為NULL。而當你做 select 時,就要使用該回調函式,因為 sqlite3 把資料查出來,得通過回撥告訴你查出了什麼資料。

資料庫對SQL語句的執行方式在下一節詳述,回撥函式的形式為:

typedef int (*sqlite3_callback)(void*,int,char**, char**)。

在SQLite資料庫中執行事務的介面也可以是sqlite3_get_table(),它返回一個表格化的結果集。不需要提供回撥函式。

4、執行SQL語句。SQL語句的執行過程由三個階段完成,下面會詳述。

5、格式化(動態構造)SQL語句,利用sqlite介面函式構造SQL語句,並呼叫相關介面執行語句。首先呼叫sqlite3_mprintf()或sqlite3_vprintf()格式化SQL語句,接著呼叫sqlite3_exec()執行語句,最後呼叫sqlite3_free()釋放記憶體資源。也可以呼叫sqlite3_exec_printf()完成整個過程。

6、斷開連線並關閉資料庫。前面如果用 sqlite3_open 開啟了一個數據庫,結尾時不要忘了還要關閉所有附加的資料庫檔案。SQLite提供介面為SQLite3_close()。

SQL語句的執行在SQLite資料庫中分兩種情況,預編譯查詢和封裝查詢。

預處理查詢是SQLite執行所有SQL命令的方式,每一個階段都關聯於語句控制代碼的一種狀態(prepared、active和finalized)。Pepared表示所有資源都已分配,對應介面函式為sqlite3_prepare(),語句已經可以執行但還沒有執行。現在還沒有申請鎖,一直到呼叫sqlite3_step()時才會申請鎖。Active狀態開始於對sqlite3_step()的呼叫,此時語句正在被執行並擁有某種鎖。Finalized意味著語句已經被關閉且所有相關資源已經被釋放。

封裝查詢是預處理查詢的封裝。在使用上比較簡單,允許你在單一的函式呼叫中執行SQL命令。一個函式是sqlite3_exec(),特別適合執行不需要返回資料的查詢。為了讓查詢結果資料返回,必須實現回撥函式,傳遞給sqlite3_exec()函式作為引數。另一個是sqlite3_get_table(),返回一個表格化的結果集。封裝查詢也可以格式化SQL語句之後再執行。

二進位制資料的資料庫處理技術

在農業資訊採集嵌入式系統中,為了滿足對採集資訊有效地在資料庫中儲存、管理、查詢和傳輸的要求,必須要對資料庫處理的關鍵技術進行研究。這些技術包括:記錄和字串處理、欄位處理、錯誤控制、操作控制和執行緒處理。

1、記錄和字串的處理是資料庫中最常用的處理方式。在前面也提到過sqlite3_exec()和sqlite3_get_table()函式是處理事務和執行SQL語句介面,區別在於sqlite3_exec()在處理記錄,如執行SELECT時,要得到處理結果需提供回撥函式。提供回撥函式的作用就是當在執行完對記錄的操作後,讓回撥函式按需要得到處理結果。字串處理主要用在對SQL語句的格式化上,在SQLite資料庫中常用介面為sqlite3_mprintf()或sqlite3_vprintf()。

2、欄位處理是在記錄操作的基礎上進行的。在SQLite中提供了以對欄位操作的函式介面,其特點是sqlite3_column_開頭。這些介面可以獲得欄位名稱、欄位的儲存型別和欄位的值等資訊。如獲得一個欄位的名稱、儲存型別和宣告型別的函式呼叫如下:

3、SQLite資料庫預定義了許多錯誤程式碼巨集以方便程式設計錯誤處理的應用。很多API介面函式的返回型別是整形,這表示返回錯誤碼,所以在介面呼叫中可以根據返回碼進行錯誤處理,可以使用函式sqlite3_errmsg()獲得附加的錯誤資訊。

影象資料在sqlite資料庫中是按照二進位制形式存放的。 操作二進位制資料需要用一個輔助的資料型別:sqlite3_stmt * 。它是一個已經把SQL語句進行了解析,並用sqlite自己標記記錄的內部資料結構來表示的SQL語句。正因為這個結構已經被解析了,所以你可以往這個語句裡插入二進位制資料。

把二進位制資料插到 sqlite3_stmt 結構的過程,必須用sqlite 提供的函式來插入。SQLite資料庫提供了一種萬用字元機制用來表示SQL語句中不確定的字元值,這些萬用字元如?、aaa、nnn等。做這些萬用字元所代表的值在sqlite3_bind_開頭的介面函式中被填充,在SQLite資料庫中提供了很多以sqlite3_bind_開頭的介面用來給SQL宣告中的萬用字元賦值。

二進位制資料的儲存相對比較複雜一點,但從資料庫對二進位制資料的操作來看,主要分為資料寫入和資料讀出。

1、資料寫入是指將二進位制資料寫到資料庫中,讓資料庫統一管理儲存。在SQLite中,二進位制資料時儲存在Blob資料型別中的。資料的寫入步驟是:建立資料庫關係表,構造含有萬用字元的插入二進位制資料的SQL語句,然後把該語句解析到sqlite3_stmt 結構中。如:

呼叫介面函式sqlite3_bind_blob()給SQL申明的萬用字元賦值,該函式第二個引數為萬用字元的索引號,從1開始,有多個萬用字元時,要多次呼叫該函式。第三個引數為二進位制資料開始指標,第四個引數為二進位制資料長度。

sqlite3_bind_blob( stat, 1, pdata, (int)(length_data), NULL );

之後,二進位制資料存放到了SQL語句。現在需要呼叫sqlite3_step()把sqlite3_stmt 結構表示的SQL語句就被寫到了資料庫裡。最後呼叫sqlite3_finalize()釋放sqlite3_stmt 結構的記憶體。

2、資料的讀出是把二進位制資料從資料庫按照記錄讀出的過程。該過程在迴圈中完成,在農業資訊採集系統中可以進行影象資訊的顯示和無線傳輸。準備sqlite3_stmt* 結構,然後把讀資料庫的SQL語句解析到sqlite3_stmt 結構中。

sqlite3_prepare( db, “select * from tab”, -1,&stat, 0 );

接著開始迴圈查詢資料,sqlite3_step( )返回SQLITE_ROW表示記錄沒有結束,否則表示結束。在迴圈中可獲取ID值、二進位制資料、二進位制資料長度和資料處理,之後釋放sqlite3_stmt* 結構記憶體。

SQLite的特性還體現在它既是一個數據庫,一個程式庫,一個命令列工具,也是一個學習關係型資料庫的很好的工具。確實有很多途徑可以把它使用到內嵌環境、網站、作業系統服務、指令碼語言和應用程式。對於程式設計師來說,SQLite就像一個數據傳送帶,提供了一種方便的將應用程式繫結的資料的方法。

第九屆中國雲端計算大會贈送的免費專業票可在指定權益範圍內參加專題論壇和主題演講,如果您覺得不夠過癮,還可以“原文連結”通過本號專屬連結購買單日通票和全場通票(團購)支援,參加更多專業精彩內容。

溫馨提示:請搜尋“ICT_Architect”或“掃一掃”下面二維碼關注公眾號,獲取更多精彩內容。

請點選此處輸入圖片描述