1.1應用樣本
在這一部分我將展示一些簡單的應用程式來說明SQLite的眾多特性。這些應用程式將在下面的一些子部分中展示
1.1.1 一個SQLite應用樣本
讓我們通過學習一個很簡單的應用程式來開始我們SQLite大陸的探險吧。下面的例子展示了一個典型的SQLite應用程式。它是一個使用SQLite API來處理一個SQLite資料庫檔案的C程式。
這是一個典型的SQLite應用程式:
#include <stdio.h> #include "sqlite3.h" int main(void) { sqlite3* db = 0; sqlite3_stmt* stmt = 0; int retcode; retcode = sqlite3_open("MyDB", &db); if (retcode != SQLITE_OK){ sqlite3_close(db); fprintf(stderr, "Could not open MyDB/n"); return retcode; } retcode = sqlite3_prepare(db, "select SID from Students order by SID", -1, &stmt, 0); if (retcode != SQLITE_OK){ sqlite3_close(db); fprintf(stderr, "Could not execute SELECT/n"); return retcode; } while (sqlite3_step(stmt) == SQLITE_ROW){ int i = sqlite3_column_int(stmt, 0); printf("SID = %d/n", i); } sqlite3_finalize(stmt); sqlite3_close(db); return SQLITE_OK; } |
你可以編譯上面的例子並且執行它。在這個文檔中顯示的樣本輸出是在一個linux機器上獲得的,但是這些例子能夠在SQLite啟動並執行其他的平台上工作
這些例子假定你已經準備了可執行檔sqlite3,libsqlite3.so(windows上是sqlite3.dll而Mac OS X上是libsqlite3.dylib)共用庫,和sqlite3.h介面定義檔案。你可以從http://www.sqlite.org上擷取這些原始碼或二進位形式的檔案。你會發現如果你將所有這三個(sqlite3, the shared library, 和sqlite3.h)和範例放在同一個目錄下處理該範例會比較容易。
舉個例子,假設你在一個Linux系統上,並且你將app1.c樣本程式儲存在libsqlite3.so , sqlite3和sqlite3.h同一個目錄下。你能夠通過執行這條命令編譯檔案:
gcc app1.c -o ./app1 -lsqlite3 -L. |
它將會在當前工作的目錄下產生一個名為app1的二進位檔案。你可以執行這個二進位檔案來查看輸出。
註: |
SQLite原始碼和應用程式必須在同一個編譯器下編譯。 如果你已經將SQLite作為一個包安裝了,或者如果你的作業系統預先安裝了SQlite,你可能需要使用一組不同的編譯參數。例如,在Ubuntu上,你可以通過命令sudo aptitude install sqlite3 libsqlite3-dev安裝SQLite,並且你可以使用命令cc app1.c -o ./app1 -lsqlite3來編譯應用程式。 因為在現行的Mac OS X版本中包含SQLite,上述的相同的編譯命令也能工作。 |
這個應用程式開啟了在當前工作目錄下的MyDB資料庫檔案。這個資料庫需要至少一個表,命名為Students;這個表必須至少有一個整型列名為SID。在下一個例子中,你將會學習如何在資料庫中建立新的表,和如何在表中插入行(也被稱為元組和記錄),但是在目前,你可以使用這些命令建立並落戶表:
sqlite3 MyDB "create table students (SID integer)" sqlite3 MyDB "insert into students values (200)" sqlite3 MyDB "insert into students values (100)" sqlite3 MyDB "insert into students values (300)" |
如果你現在運行app1(在linux系統下要引入SQLite庫,,你可能需要在LD_LIBRARY_PATH環境變數中加入你的工作目錄名字,你將會看到下面的輸出:
SID = 100 SID = 200 SID = 300 |
註: |
在Linux,Unix和Mac OS X中,在命令提示字元中鍵入app1的名字時,你可能需要首碼./ ./app1 |
應用程式首先做好準備工作,接著執行SQL語句:select SID from Students order by SID。然後它進階到作為結果的行集,一個接一個的擷取SID的值,並且列印各個值。最後關閉資料庫。
SQLite是一個調用層級上的介面庫,它能夠嵌入到應用程式中。該庫將所有的SQLite API函數實現為C函數。所有的API函數都是以sqlite3_首碼命名,並且在sqlite3.h中聲明。在應用程式範例中使用了他們中的一部分,他們是sqlite3_open, sqlite3_prepare, sqlite3_step, sqlite3_column_int, sqlite3_finalize, 和 sqlite3_close。應用程式也採用了助記符常量,即用於API的返回比較值的SQLITE_OK 和 SQLITE_ROW。這些助記符在sqlite3.h中被定義。
1.1.1.1 sqlite3_open
通過執行sqlite3_open函數,應用程式經由SQLite庫開啟了一個到資料庫檔案的新串連。(該應用程式可能有其他到相同的或者不同的資料庫的開放串連。SQLite清楚地處理這些串連,並且他們在SQLite注意前是相互間獨立的)。如果檔案還不存在,SQLite將自動的建立資料庫檔案。
註: |
在開啟或建立一個檔案時,SQLite遵守一個懶惰策略:知道該檔案被閱讀訪問時才真正的開啟或者建立。 |
sqlite3_open函數經由一個形參(db,在前面的例子中)返回一個串連控制代碼(一個指向sqlite3類型的對象的指標),而控制代碼被用來支援在資料庫連接(因為這次開啟串連)上的進一步操作。控制代碼表示了這次串連的完整情況。
1.1.1.2 sqlite3_prepare
sqlite3_prepare函數編譯了一個SQL語句,並且產生了一個等價的內部對象。這個對象在資料庫文法中作為一個準備語句被普遍的提及,在SQLite中他被實現為一個位元組編碼程式。位元組編碼程式是在虛擬機器或者解譯器上啟動並執行SQL語言的一個抽象表示。想要得到更多的資訊,看後面的部分位元組編碼程式設計語言。在本書中,我將交替使用條件位元組編碼程式和準備語句。
sqlite3_prepare函數經由一個形參(在前面例子中的stmt)返回一個狀態控制代碼(指向sqlite3_stmt類型對象的指標),該控制代碼被用來支援進一步的操作來操縱準備狀態。在這個樣本程式中,我準備了select SID from Students order by SID語句作為stmt控制代碼。這個控制代碼動作起來就像一個開放的游標並且他被用來擷取SELECT語句返回的作為結果的行集,一次一行。
1.1.1.3 sqlite3_step
sqlite3_step函數將執行位元組編碼程式直到它遇到折點(因為它已經計算了新的一行),或者直到它停止(沒有剩下的行了)。在之前的例子中,他返回了SQLITE_ROW,而在之後的例子中是SQLITE_DONE。因為有的SQL語句不返回行(例如UPDATE,INSERT,DELETE,和CREATE),當沒有行要處理時,他總是返回SQLITE_DONE。Step函數移動指標的位置來獲得SELECT語句的結果。初始的,指標指向輸出行集的第一行的前一位置。執行一次step函數,指標移動到了輸出行集的下一行。該指標只能向前移動。
1.1.1.4 sqlite3_column_int
如果step函數返回了SQLITE_ROW,你能夠通過執行sqlite3_column_*API函數來檢索每一列(也被認為是屬性或域)的值。SQL/SQLite和C語言中的阻抗(資料類型)的不匹配能夠被自動的處理:API在兩種語言間,將資料進行從儲存類型到請求類型的轉換。在樣本應用中,每個輸出行是一個整型值,我們通過執行返回整型值的sqlite3_column_int函數來讀取的SID的值。
1.1.1.5 sqlite3_finalize
sqlite3_finalize函數銷毀準備好的狀態。也就是說,擦除位元組編碼程式,並且釋放分配給狀態控制代碼的所有資源。控制代碼變為不可用。
1.1.1.6 sqlite3_close
sqlite3_close函數關閉資料庫連接,並且釋放了分配給該串連的所有資源。該串連控制代碼變為不可用。
1.1.1.7 其他有用的函數
其它被廣泛使用的API是sqlite3_bind_*和sqlite3_reset。在一個SQL語句字串(輸入到sqlite3_prepare),一個或者多個文本值能夠被SQL參數標識?(或者?NNN,:AAA,@AAA或者$AAA,其中NNN是一個數字,而AAA是一個標示符)來代替。他們成為準備語句的輸入參數這些參數的值可以通過使用bind API函數來設定。如果一個參數沒有值約束,那麼它不是取預設值,就是在沒有預設值被聲明的時候取SQL NULL。reset API函數通過一個異常將狀態控制代碼(例如,準備狀態)重設回它的初始狀態:所有有制約值的參數保持他們的原值。狀態準備被應用程式再一次的執行,並且在再執行過程中重用這些值。然而,應用程式可能會在它開始重新執行的前再一次的執行bind API獲得新值來代替前值。
1.1.1.8 傳回值
所有的API函數返回0或者負整數值。SQLite推薦使用助記符來核對傳回值。傳回值SQLITE_OK表示成功。SQLITE_ROW表示sqlite3_step函數在SELECT語句返回的行集中找到了新的一行;SQLITE_DONE表示語句執行完成了。