1.0 總覽
SQLite3是SQLite一個全新的版本,它雖然是在SQLite 2.8.13的代碼基礎之上開發的,但是使用了和之前的版本不兼容的數據庫格式和API. SQLite3是為了滿足以下的需求而開發的:
l 支持UTF-16編碼.
l 用戶自定義的文本排序方法.
l 可以對BLOBs字段建立索引.
因此為了支持這些特性我改變了數據庫的格式,建立了一個與之前版本不兼容的3.0版. 至于其他的兼容性的改變,例如全新的API等等,都將在理論介紹之后向你說明,這樣可以使你最快的一次性擺脫兼容性問題.
3.0版的和2.X版的API非常相似,但是有一些重要的改變需要注意. 所有API接口函數和數據結構的前綴都由"sqlite_"改為了"sqlite3_". 這是為了避免同時使用SQLite 2.X和SQLite 3.0這兩個版本的時候發生鏈接沖突.
由于對于C語言應該用什么數據類型來存放UTF-16編碼的字符串并沒有一致的規范. 因此SQLite使用了普通的void* 類型來指向UTF-16編碼的字符串. 客戶端使用過程中可以把void*映射成適合他們的系統的任何數據類型.
2.0 C/C++ 接口
SQLite 3.0一共有83個API函數,此外還有一些數據結構和預定義(#defines). (完整的API介紹請參看另一份文檔.) 不過你們可以放心,這些接口使用起來不會像它的數量所暗示的那么復雜. 最簡單的程序仍然使用三個函數就可以完成: sqlite3_open(), sqlite3_exec(),和 sqlite3_close(). 要是想更好的控制數據庫引擎的執行,可以使用提供的sqlite3_prepare()函數把SQL語句編譯成字節碼,然后在使用sqlite3_step()函數來執行編譯后的字節碼. 以sqlite3_column_開頭的一組API函數用來獲取查詢結果集中的信息. 許多接口函數都是成對出現的,同時有UTF-8和UTF-16兩個版本. 并且提供了一組函數用來執行用戶自定義的SQL函數和文本排序函數.
2.1 如何打開關閉數據庫
typedef struct sqlite3 sqlite3;
int sqlite3_open(const char*, sqlite3**);
int sqlite3_open16(const void*, sqlite3**);
int sqlite3_close(sqlite3*);
const char *sqlite3_errmsg(sqlite3*);
const void *sqlite3_errmsg16(sqlite3*);
int sqlite3_errcode(sqlite3*);
sqlite3_open() 函數返回一個整數錯誤代碼,而不是像第二版中一樣返回一個指向sqlite3結構體的指針. sqlite3_open() 和 sqlite3_open16() 的不同之處在于sqlite3_open16() 使用UTF-16編碼(使用本地主機字節順序)傳遞數據庫文件名. 如果要創建新數據庫, sqlite3_open16() 將內部文本轉換為UTF-16編碼, 反之sqlite3_open() 將文本轉換為UTF-8編碼.
打開或者創建數據庫的命令會被緩存,直到這個數據庫真正被調用的時候才會被執行. 而且允許使用PRAGMA聲明來設置如本地文本編碼或默認內存頁面大小等選項和參數.
sqlite3_errcode() 通常用來獲取最近調用的API接口返回的錯誤代碼. sqlite3_errmsg()則用來得到這些錯誤代碼所對應的文字說明. 這些錯誤信息將以 UTF-8 的編碼返回,并且在下一次調用任何SQLite API函數的時候被清除. sqlite3_errmsg16() 和 sqlite3_errmsg() 大體上相同,除了返回的錯誤信息將以 UTF-16 本機字節順序編碼.
SQLite3的錯誤代碼相比SQLite2沒有任何的改變,它們分別是:
#define SQLITE_OK 0 /* Successful result */
#define SQLITE_ERROR 1 /* SQL error or missing database */
#define SQLITE_INTERNAL 2 /* An internal logic error in SQLite */
#define SQLITE_PERM 3 /* Access permission denied */
#define SQLITE_ABORT 4 /* Callback routine requested an abort */
#define SQLITE_BUSY 5 /* The database file is locked */
#define SQLITE_LOCKED 6 /* A table in the database is locked */
#define SQLITE_NOMEM 7 /* A malloc() failed */
#define SQLITE_READONLY 8 /* Attempt to write a readonly database */
#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite_interrupt() */
#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */
#define SQLITE_CORRUPT 11 /* The database disk image is malformed */
#define SQLITE_NOTFOUND 12 /* (Internal Only) Table or record not found */
#define SQLITE_FULL 13 /* Insertion failed because database is full */
#define SQLITE_CANTOPEN 14 /* Unable to open the database file */
#define SQLITE_PROTOCOL 15 /* Database lock protocol error */
#define SQLITE_EMPTY 16 /* (Internal Only) Database table is empty */
#define SQLITE_SCHEMA 17 /* The database schema changed */
#define SQLITE_TOOBIG 18 /* Too much data for one row of a table */
#define SQLITE_CONSTRAINT 19 /* Abort due to contraint violation */
#define SQLITE_MISMATCH 20 /* Data type mismatch */
#define SQLITE_MISUSE 21 /* Library used incorrectly */
#define SQLITE_NOLFS 22 /* Uses OS features not supported on host */
#define SQLITE_AUTH 23 /* Authorization denied */
#define SQLITE_ROW 100 /* sqlite_step() has another row ready */
#define SQLITE_DONE 101 /* sqlite_step() has finished executing */
2.2 執行 SQL 語句
typedef int (*sqlite_callback)(void*,int,char**, char**);
int sqlite3_exec(sqlite3*, const char *sql, sqlite_callback, void*, char**);
sqlite3_exec 函數依然像它在SQLite2中一樣承擔著很多的工作. 該函數的第二個參數中可以編譯和執行零個或多個SQL語句. 查詢的結果返回給回調函數. 更多地信息可以查看API 參考.
在SQLite3里,sqlite3_exec一般是被準備SQL語句接口封裝起來使用的.
typedef struct sqlite3_stmt sqlite3_stmt;
int sqlite3_prepare(sqlite3*, const char*, int, sqlite3_stmt**, const char**);
int sqlite3_prepare16(sqlite3*, const void*, int, sqlite3_stmt**, const void**);
int sqlite3_finalize(sqlite3_stmt*);
int sqlite3_reset(sqlite3_stmt*);
sqlite3_prepare 接口把一條SQL語句編譯成字節碼留給后面的執行函數. 使用該接口訪問數據庫是當前比較好的的一種方法.
sqlite3_prepare() 處理的SQL語句應該是UTF-8編碼的. 而sqlite3_prepare16() 則要求是UTF-16編碼的. 輸入的參數中只有第一個SQL語句會被編譯. 第四個參數則用來指向輸入參數中下一個需要編譯的SQL語句存放的SQLite statement對象的指針, 任何時候如果調用sqlite3_finalize() 將銷毀一個準備好的SQL聲明. 在數據庫關閉之前,所有準備好的聲明都必須被釋放銷毀. sqlite3_reset() 函數用來重置一個SQL聲明的狀態,使得它可以被再次執行.
SQL聲明可以包含一些型如"?" 或 "?nnn" 或 ":aaa"的標記,其中"nnn" 是一個整數,"aaa" 是一個字符串. 這些標記代表一些不確定的字符值(或者說是通配符),可以在后面用sqlite3_bind 接口來填充這些值. 每一個通配符都被分配了一個編號(由它在SQL聲明中的位置決定,從1開始),此外也可以用 "nnn" 來表示 "?nnn" 這種情況. 允許相同的通配符在同一個SQL聲明中出現多次, 在這種情況下所有相同的通配符都會被替換成相同的值. 沒有被綁定的通配符將自動取NULL值.
int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
int sqlite3_bind_double(sqlite3_stmt*, int, double);
int sqlite3_bind_int(sqlite3_stmt*, int, int);
int sqlite3_bind_int64(sqlite3_stmt*, int, long long int);
int sqlite3_bind_null(sqlite3_stmt*, int);
int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*));
int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
以上是 sqlite3_bind 所包含的全部接口,它們是用來給SQL聲明中的通配符賦值的. 沒有綁定的通配符則被認為是空值. 綁定上的值不會被sqlite3_reset()函數重置. 但是在調用了sqlite3_reset()之后所有的通配符都可以被重新賦值.
在SQL聲明準備好之后(其中綁定的步驟是可選的), 需要調用以下的方法來執行:
int sqlite3_step(sqlite3_stmt*);
如果SQL返回了一個單行結果集,sqlite3_step() 函數將返回 SQLITE_ROW , 如果SQL語句執行成功或者正常將返回 SQLITE_DONE , 否則將返回錯誤代碼. 如果不能打開數據庫文件則會返回 SQLITE_BUSY . 如果函數的返回值是 SQLITE_ROW, 那么下邊的這些方法可以用來獲得記錄集行中的數據:
const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);
int sqlite3_column_bytes(sqlite3_stmt*, int iCol);
int sqlite3_column_bytes16(sqlite3_stmt*, int iCol);
int sqlite3_column_count(sqlite3_stmt*);
const char *sqlite3_column_decltype(sqlite3_stmt *, int iCol);
const void *sqlite3_column_decltype16(sqlite3_stmt *, int iCol);
double sqlite3_column_double(sqlite3_stmt*, int iCol);
int sqlite3_column_int(sqlite3_stmt*, int iCol);
long long int sqlite3_column_int64(sqlite3_stmt*, int iCol);
const char *sqlite3_column_name(sqlite3_stmt*, int iCol);
const void *sqlite3_column_name16(sqlite3_stmt*, int iCol);
const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);
const void *sqlite3_column_text16(sqlite3_stmt*, int iCol);
int sqlite3_column_type(sqlite3_stmt*, int iCol);
sqlite3_column_count()函數返回結果集中包含的列數. sqlite3_column_count() 可以在執行了 sqlite3_prepare()之后的任何時刻調用. sqlite3_data_count()除了必需要在sqlite3_step()之后調用之外,其他跟sqlite3_column_count() 大同小異. 如果調用sqlite3_step() 返回值是 SQLITE_DONE 或者一個錯誤代碼, 則此時調用sqlite3_data_count() 將返回 0 ,然而 sqlite3_column_count() 仍然會返回結果集中包含的列數.
返回的記錄集通過使用其它的幾個 sqlite3_column_***() 函數來提取, 所有的這些函數都把列的編號作為第二個參數. 列編號從左到右以零起始. 請注意它和之前那些從1起始的參數的不同.
sqlite3_column_type()函數返回第N列的值的數據類型. 具體的返回值如下:
#define SQLITE_INTEGER 1
#define SQLITE_FLOAT 2
#define SQLITE_TEXT 3
#define SQLITE_BLOB 4
#define SQLITE_NULL 5
sqlite3_column_decltype() 則用來返回該列在 CREATE TABLE 語句中聲明的類型. 它可以用在當返回類型是空字符串的時候. sqlite3_column_name() 返回第N列的字段名. sqlite3_column_bytes() 用來返回 UTF-8 編碼的BLOBs列的字節數或者TEXT字符串的字節數. sqlite3_column_bytes16() 對于BLOBs列返回同樣的結果,但是對于TEXT字符串則按 UTF-16的編碼來計算字節數. sqlite3_column_blob() 返回 BLOB 數據. sqlite3_column_text() 返回 UTF-8 編碼的 TEXT 數據. sqlite3_column_text16() 返回 UTF-16 編碼的 TEXT 數據. sqlite3_column_int() 以本地主機的整數格式返回一個整數值. sqlite3_column_int64() 返回一個64位的整數. 最后, sqlite3_column_double() 返回浮點數.
不一定非要按照sqlite3_column_type()接口返回的數據類型來獲取數據. 數據類型不同時軟件將自動轉換.
2.3 用戶自定義函數
可以使用以下的方法來創建用戶自定義的SQL函數:
typedef struct sqlite3_value sqlite3_value;
int sqlite3_create_function(
sqlite3 *,
const char *zFunctionName,
int nArg,
int eTextRep,
void*,
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
void (*xFinal)(sqlite3_context*)
);
int sqlite3_create_function16(
sqlite3*,
const void *zFunctionName,
int nArg,
int eTextRep,
void*,
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
void (*xFinal)(sqlite3_context*)
);
#define SQLITE_UTF8 1
#define SQLITE_UTF16 2
#define SQLITE_UTF16BE 3
#define SQLITE_UTF16LE 4
#define SQLITE_ANY 5
nArg 參數用來表明自定義函數的參數個數. 如果參數值為0,則表示接受任意個數的參數.用 eTextRep 參數來表明傳入參數的編碼形式. 參數值可以是上面的五種預定義值. SQLite3允許同一個自定義函數有多種不同的編碼參數的版本. 數據庫引擎會自動選擇轉換參數編碼個數最少的版本使用.
普通的函數只需要設置 xFunc 參數,而把 xStep 和 xFinal 設為NULL. 聚合函數則需要設置 xStep 和 xFinal 參數,然后把 xFunc 設為NULL. 該方法和使用sqlite3_create_aggregate() API一樣.
sqlite3_create_function16()和sqlite_create_function()的不同就在于自定義的函數名一個要求是 UTF-16 編碼,而另一個則要求是 UTF-8.
請注意自定函數的參數目前使用了sqlite3_value結構體指針替代了SQLite version 2.X中的字符串指針. 下面的函數用來從sqlite3_value結構體中提取數據:
const void *sqlite3_value_blob(sqlite3_value*);
int sqlite3_value_bytes(sqlite3_value*);
int sqlite3_value_bytes16(sqlite3_value*);
double sqlite3_value_double(sqlite3_value*);
int sqlite3_value_int(sqlite3_value*);
long long int sqlite3_value_int64(sqlite3_value*);
const unsigned char *sqlite3_value_text(sqlite3_value*);
const void *sqlite3_value_text16(sqlite3_value*);
int sqlite3_value_type(sqlite3_value*);
上面的函數調用以下的API來獲得上下文內容和返回結果:
void *sqlite3_aggregate_context(sqlite3_context*, int nbyte);
void *sqlite3_user_data(sqlite3_context*);
void sqlite3_result_blob(sqlite3_context*, const void*, int n, void(*)(void*));
void sqlite3_result_double(sqlite3_context*, double);
void sqlite3_result_error(sqlite3_context*, const char*, int);
void sqlite3_result_error16(sqlite3_context*, const void*, int);
void sqlite3_result_int(sqlite3_context*, int);
void sqlite3_result_int64(sqlite3_context*, long long int);
void sqlite3_result_null(sqlite3_context*);
void sqlite3_result_text(sqlite3_context*, const char*, int n, void(*)(void*));
void sqlite3_result_text16(sqlite3_context*, const void*, int n, void(*)(void*));
void sqlite3_result_value(sqlite3_context*, sqlite3_value*);
void *sqlite3_get_auxdata(sqlite3_context*, int);
void sqlite3_set_auxdata(sqlite3_context*, int, void*, void (*)(void*));
2.4 用戶自定義排序規則
下面的函數用來實現用戶自定義的排序規則:
sqlite3_create_collation(sqlite3*, const char *zName, int eTextRep, void*,
int(*xCompare)(void*,int,const void*,int,const void*));
sqlite3_create_collation16(sqlite3*, const void *zName, int eTextRep, void*,
int(*xCompare)(void*,int,const void*,int,const void*));
sqlite3_collation_needed(sqlite3*, void*,
void(*)(void*,sqlite3*,int eTextRep,const char*));
sqlite3_collation_needed16(sqlite3*, void*,
void(*)(void*,sqlite3*,int eTextRep,const void*));
sqlite3_create_collation() 函數用來聲明一個排序序列和實現它的比較函數. 比較函數只能用來做文本的比較. eTextRep 參數可以取如下的預定義值 SQLITE_UTF8, SQLITE_UTF16LE, SQLITE_UTF16BE, SQLITE_ANY,用來表示比較函數所處理的文本的編碼方式.同一個自定義的排序規則的同一個比較函數可以有 UTF-8, UTF-16LE 和 UTF-16BE 等多個編碼的版本. sqlite3_create_collation16()和sqlite3_create_collation() 的區別也僅僅在于排序名稱的編碼是 UTF-16 還是 UTF-8.
可以使用 sqlite3_collation_needed() 函數來注冊一個回調函數,當數據庫引擎遇到未知的排序規則時會自動調用該函數. 在回調函數中可以查找一個相似的比較函數,并激活相應的sqlite_3_create_collation()函數. 回調函數的第四個參數是排序規則的名稱,同樣sqlite3_collation_needed采用 UTF-8 編碼. sqlite3_collation_need16() 采用 UTF-16編碼.