SQLite 第三版C/C++介面
1.0 概述
SQLite 3.0是SQLite的新版本,它繼承於SQLite 2.8.13,但帶有一個不相容的檔案格式和API。SQLite 3.0依據以下需求而建立:
- 支援UTF-16。
- 使用者可定義的文本排序。
- 以索引列的形式儲存BLOB。
必須遷移到3.0版來實現的原因是每一個改變與資料庫檔案格式不相容。另外一些不相容的改變,如清除的API,在下面的理論中介紹最好是一次性去掉你的不相容的變化。
3.0版的API與2.X版的相似,但也有一些重要的改變。最顯著的是出現在所有的API函數和資料據結構前的“sqlite_”首碼被改為“sqlite3_”。這避免二類API間的混亂並且允許連結器同時應對SQLite 2.X和SQLite 3.0。
在UTF-16的C類型應該是什麼樣子上沒有統一。因此,SQLite用一個通用的類型void *來指向UTF-16字串。客戶軟體可以轉換void*到任何與之系統相適應的資料類型。
2.0 C/C++介面
除了幾個資料結構和#define,SQLite 3.0的API包括了83個獨立的函數。(一個完整的API參考作為一個獨立的文檔提供。)幸運的是,介面不是與它所顯示的大小一般複雜。簡單的程式仍可以通過僅僅三個函數工作:sqlite3_open()、sqlite3_exec()和sqlite3_close()。更多的資料庫引擎運行控制可以用sqlite3_prepare()來編譯一個SQLite語句成位元組代碼並通過sqlite3_step()來執行它。一個用sqlite3_column_開頭的命令序列可以用來提取關於查詢結果的資訊。許多介面函數是以UTF-8和UTF-16的形式成對出現的。並且有一個用於實現使用者定義SQL函數和使用者定義的text比較。
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()程式返回一個整型錯誤碼,而不是像sqlite2做的那樣返回一個指向sqlite3結構。sqlite3_open()與sqlite3_open16()間的區別是sqlite3_open16()採用UTF-16(以本地位元組順序)作為資料庫檔案名。如果一個新資料庫檔案需要被建立,那麼sqlite3_open16()設定本地的文本運算式為UTF-16而sqlite3_open()設定文本運算式為UTF-8。
資料庫檔案開啟與建立延遲到使用者實際的時候(被開啟或建立)。這允許可選項和參數,如本地文本表示和預設的頁大小,通過用PRAGMA語句設定。
sqlite3_errcode()指令返回一個最近的主API調用的結果代碼。sqlite3_errmsg()返回一個最近錯誤的英文資訊。錯誤碼資訊可能是暫時的 - 它可能在接下來的任何SQLite函數調用時消失。sqlite3_errmsg16()象sqlite3_errsmg()一樣工作,除了它以本地位元組順序返回一個UTF-16錯誤資訊。
SQLite 3 的錯誤碼與版本2相比並沒有變化。它們如下所示
#define SQLITE_OK 0 /* 成功的結果 */#define SQLITE_ERROR 1 /* SQL 錯誤或沒有資料庫 */#define SQLITE_INTERNAL 2 /* 一個SQLite內部的邏輯錯誤 */#define SQLITE_PERM 3 /* 存取許可被拒絕 */#define SQLITE_ABORT 4 /* 需要一個中斷的Callback指令 */#define SQLITE_BUSY 5 /* 資料據庫檔案被鎖定 */#define SQLITE_LOCKED 6 /* 資料庫中的一個表被鎖定 */#define SQLITE_NOMEM 7 /* malloc()失敗 */#define SQLITE_READONLY 8 /* 試圖寫一個唯讀資料庫 */#define SQLITE_INTERRUPT 9 /* 操作被sqlite_interrupt()結束 */#define SQLITE_IOERR 10 /* 某種磁碟I/O錯誤發生 */#define SQLITE_CORRUPT 11 /* 資料庫磁碟鏡像異常 */#define SQLITE_NOTFOUND 12 /* (Internal Only) 表或記錄不存在 */#define SQLITE_FULL 13 /* 資料庫滿插入失敗 */#define SQLITE_CANTOPEN 14 /* 不能開啟資料庫檔案 */#define SQLITE_PROTOCOL 15 /* 資料庫錯定協議錯 */#define SQLITE_EMPTY 16 /* (Internal Only)資料庫表為空白 */#define SQLITE_SCHEMA 17 /* 資料庫結構被改變 */#define SQLITE_TOOBIG 18 /* 一個表的行資料過多 */#define SQLITE_CONSTRAINT 19 /* 由於約束衝突而中止 */#define SQLITE_MISMATCH 20 /* 資料類型不匹配 */#define SQLITE_MISUSE 21 /* 庫被不正確使用 */#define SQLITE_NOLFS 22 /* 主機不支援的OS特性 */#define SQLITE_AUTH 23 /* 授權被否定 */#define SQLITE_ROW 100 /* sqlite_step()有另一行就緒 */#define SQLITE_DONE 101 /* sqlite_step()已經完成執行 */
2.2 執行SQL語句
typedef int (*sqlite_callback)(void*,int,char**, char**);int sqlite3_exec(sqlite3*, const char *sql, sqlite_callback, void*, char**);
sqlite3_exec()函數的工作與SQLite 2版本中的方式非常像。在第二個參數中給出的0或多個SQL語句被編譯執行。查詢結果被返回給予個Callback函數。更多的資訊參見API參考。
在SQLite 3中,sqlite3_exec()函數像包含一個預定義語句介面的調用的容器。
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外。只有輸入字串的第一個語句被編譯。第四個參數被一個指向下一個(未編譯的)SQLite語句的指標,如果有的話。sqlite3_finalize()函數處理一個準備好的SQL語句。在資料庫關閉前所有的準備好的SQL語句必須被結束。sqlite_reset()函數重設準備好的語句以便於它可以被再一次執行。
SQL語句可以包含“?”或“?nnn”或":aa“標識符這裡"nnn"是一個整數而"aa"是一個標識。這些標識符表示未定義的文字值(或者“萬用字元”)(它們)為後面的sqlite3_bind介面所填寫充。每個萬用字元有一個相應的資料它是在運算式中的序列或者"nnn"以一個"?nnn"的形式。這允許同樣的萬用字元出現而不是在該語句中出現一次,在這種情況下萬用字元將被以相同的值真充。無約束的萬用字元將有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指令用於給準備好的語句指派指的分類。無定義萬用字元被解釋為NULL。綁定不能被sqlite3_reset重設。但萬用字元在sqlite3_reset之後可以被重新綁定為新值。
一個SQL語句準備好之後(可選界定),它以用下面語句執行:
int sqlite3_step(sqlite3_stmt*);sqlite3_step()指令在返回結果集的一條記錄時返回SQLITE_ROW,或者如果完成執行剛返回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_cloumn_count()可以在sqlite3_prepare()之後任意時刻調用。sqlte3_data_count()的功能與sqlite3_column_count()相似除了它只在sqlite3_step()後使用有效。如果當前調用了sqlite3_step()返回SQLITE_DONE或者一個錯誤碼,那麼sqlite3_data_count()將返回0除此之外sqlite3_cloumn_count()將繼續返回結果集的行數。
返回結果通過另外的sqlite3_column_***()函數檢查,所有的都帶有一個列號作為它們的第二參數。列是從左至右從0開始運引。注意這與參數不同,它是從一開始索引。
sqlite3_column_type()函數返回第幾列的資料類型。傳回值是以下值之一:
#define SQLITE_INTEGER 1 #define SQLITE_FLOAT 2 #define SQLITE_TEXT 3 #define SQLITE_BLOB 4 #define SQLITE_NULL 5sqlite3_column_decltype()返回一個以CREATE TABLE語句聲明列類型文本。對於一個運算式來說,傳回值是一個Null 字元串。sqlite3_column_bytes()返回第n列的名字。sqlite3_column_bytes()返回一個類型為BLOB或UTF-8編碼的TEXT類型的位元組數。sqlite3_column_bytes16()對BLOB類型返回相同的值而TEXT類型返回以UTF-16編碼的位元組數。sqlite3_column_text()返回UTF-8資料。sqlite3_column_text16()返回UTF-16資料。sqlite3_column_int()返回主機本地的INTEGER資料。sqlite_column_int64返回64位整數。最後,sqlite_column_duble()返回浮點類型的數。
通過sqlite3_column_type()擷取資料不是必須的。如果一個不同的格式需要的時候,資料類型將會自動轉換。
2.3 使用者定義函數
使用者定義函數可以用下面的涵數實現:
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參數指明在這個函數中何種文本描述值。這個參數值應該是上面定義的一個類型。SQLite 3允許相同函數用不同的運算式。資料庫引擎最小數量文本轉換需要。
通常函數公指定xFunc並保持xFunc和xStep為空白。彙總函數指定xStep和xFinal並保持xFunc為空白。sqlite3_create_aggregate()API也一樣。
函數名用UTF-8指定。一個分離的sqlite_craetefunction16()API作用與sqlite_create_function()相同除了函數名用UTF-16主機位元組順指定。
注意函數參數是是一個指向sqlite3_value結構的指標而不是像SQLite 2.X指向字串的指標。接下來的函數用來從下面這些值中取得有用的資訊:
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_UTF16, SQLITE_UTF16BE或SQLITE_ANY中之一來指定用哪個文本運算式工作。
面對相同的UTF-8, UTF-16LE和UTF-16BE匯總序列獨立的比較函數存在。
sqlite3_create_collation16()功能與sqlite3_create_collation()一樣,除了排序的名字被主機位元組順序列的UTF-16代替UTF-8。
sqlite3_collation_needed()函數註冊Callback函數在遇到未知的排序序列時讓資料庫引擎調用。
Callback函數可以尋找一個相應的比較函數並在必要的時候調用sqlit3_create_collation()。
Callback函數的第四個參數是UTF-8格式的匯總序列的名字。
對於sqlite3_collatin_need16()函數,Callback函數調用發送主機位元組順序的UTF-16匯總序列名。