SQLite3 API 包括很多函數(shù)振愿,但是只有大概8個(gè)函數(shù)是實(shí)際處理連接毅糟、查詢红选、斷開與數(shù)據(jù)庫(kù)連接所必需的。
一留特、查詢封裝
1纠脾、連接與斷開連接
執(zhí)行SQL命令前,要先連接數(shù)據(jù)庫(kù)蜕青,也叫打開數(shù)據(jù)庫(kù)。結(jié)束時(shí)糊渊,要斷開連接右核,也叫關(guān)閉數(shù)據(jù)庫(kù)。
打開數(shù)據(jù)庫(kù)的函數(shù)有:
- sqlite3_open_v2():推薦使用
- sqlite3_open()
- sqlite3_open16()
int sqlite3_open_v2(
const char *filename, /*數(shù)據(jù)庫(kù)文件名*/
sqlite3 **ppDb /*OUT:SQLite數(shù)據(jù)庫(kù)句柄*/
int flags, /*標(biāo)志*/
const char *zVfs /*要使用的VFS模塊的名稱*/
)
說(shuō)明:
- filename:可以為操作系統(tǒng)文件渺绒、文本字符串‘memory’贺喝、空字符串。filename為‘memory’時(shí)宗兼,表示將在內(nèi)存中創(chuàng)建數(shù)據(jù)庫(kù)躏鱼;為空字符串或null時(shí),表示打開臨時(shí)磁盤文件殷绍,并在連接關(guān)閉時(shí)自動(dòng)刪除文件染苛。為其他選項(xiàng)時(shí),嘗試打開參數(shù)指定的文件主到,若文件不存在且flags不等于SQLITE_OPEN_CREATE茶行,則返回錯(cuò)誤。
- ppDb:在打開完成后登钥,sqlite3_open_v2會(huì)初始化sqlite3結(jié)構(gòu)體傳遞給ppDb參數(shù)畔师,是事務(wù)上下文環(huán)境。代表一個(gè)連接句柄牧牢,而不是一個(gè)數(shù)據(jù)庫(kù)句柄看锉,因?yàn)榭赡軙?huì)附加多個(gè)數(shù)據(jù)庫(kù)到一個(gè)連接上姿锭。
- flags:是一個(gè)比特向量,包括以下幾種值:SQLite_OPEN_READONLY伯铣、SQLite_OPEN_READWRITE呻此、SQLITE_OPEN_CREATE等。SQLite_OPEN_READONLY懂傀、SQLite_OPEN_READWRITE分別表示只讀和讀/寫模式打開數(shù)據(jù)庫(kù)趾诗,若文件不存在,就返回錯(cuò)誤蹬蚁。
- zVfs:表示允許調(diào)用者覆寫默認(rèn)的sqlite3_vfs操作系統(tǒng)接口恃泪。
關(guān)閉連接的函數(shù):
int sqlite3_close(sqlite3*);
說(shuō)明:
- sqlite3_close要成功執(zhí)行,須完成連接中所有的查詢犀斋。若有一個(gè)未完成贝乎,就會(huì)返回SQLITE_BUSY,并顯示錯(cuò)誤消息叽粹。
- sqlite3_close關(guān)閉連接時(shí)览效,若連接上有打開的事務(wù),該事務(wù)將自動(dòng)回滾虫几。
2锤灿、執(zhí)行查詢
執(zhí)行SQL命令的函數(shù):
int sqlite3_exec(
sqlite3*, /*打開的數(shù)據(jù)庫(kù)*/
const char *sql, /*要執(zhí)行的SQL*/
sqlite_callback, /*回調(diào)函數(shù)*/
void *data /*回調(diào)函數(shù)的第一個(gè)參數(shù)*/
char **errmsg /*錯(cuò)誤信息*/
);
說(shuō)明:
- sqlite3_exec()解析執(zhí)行sql語(yǔ)句中的每個(gè)命令,知道遇到該字符串的末尾或遇到錯(cuò)誤辆脸。
- sqlite3_exec()提供了獲取select語(yǔ)句結(jié)果的回調(diào)機(jī)制但校。
- sqlite_callback:回調(diào)函數(shù)的指針,調(diào)用函數(shù)會(huì)處理每個(gè)sql語(yǔ)句中執(zhí)行的select語(yǔ)句的結(jié)果啡氢。
sqlite_callback回調(diào)函數(shù)的聲明:
typedef int (*sqlite3_callback)(
void*, /*該參數(shù)就是sqlite3_exec的第四個(gè)參數(shù)提供的數(shù)據(jù)*/
int, /*行中字段的數(shù)目*/
char**, /*代表行中字段名稱的字符串?dāng)?shù)組*/
char** /*代表字段名稱的字符串?dāng)?shù)組*/
)
說(shuō)明:
- sqlite3_callback回調(diào)函數(shù)的返回值状囱,會(huì)影響sqlite3_exec()的執(zhí)行。若返回非零值倘是,sqlite3_exec()將會(huì)終止亭枷。
3、獲取表查詢
函數(shù)聲明如下:
int sqlite3_get_table(
sqlite3*, /*打開的數(shù)據(jù)庫(kù)*/
const char *sql, /*要執(zhí)行的SQL語(yǔ)句*/
char ***resultp, /*結(jié)果寫入該指針指向的char*[]*/
int *nrow, /*結(jié)果集中行的數(shù)目*/
int *ncolumn, /*結(jié)果集中字段的數(shù)目*/
char **errmsg /*錯(cuò)誤信息*/
)
說(shuō)明:
- resultp:堆上聲明的內(nèi)存搀崭,將返回的記錄都存儲(chǔ)在resultp中叨粘,必須使用sqlite3_free_table()釋放內(nèi)存。
- resultp的前幾個(gè)元素實(shí)際上不是真的記錄门坷,而是結(jié)果集中的列名稱宣鄙。
二、查詢準(zhǔn)備
相比于sqlite3_exec()和sqlite3_get_table()默蚌,準(zhǔn)備查詢提供了更多的功能冻晤,更好的控制和更多的信息。
實(shí)際上绸吸,sqlite3_exec()更適合運(yùn)行修改數(shù)據(jù)庫(kù)的命令(create鼻弧、drop设江、insert、update攘轩、delete)叉存。而準(zhǔn)備查詢更適合select語(yǔ)句,因?yàn)樗梢蕴峁└嗟男畔⒍劝铮⑶铱梢酝ㄟ^游標(biāo)來(lái)遍歷結(jié)果集歼捏。
下面就準(zhǔn)備查詢的整個(gè)過程及三個(gè)步驟:編譯、執(zhí)行笨篷、完成來(lái)進(jìn)行詳細(xì)解釋瞳秽。
1、編譯
編譯或者準(zhǔn)備一個(gè)SQL語(yǔ)句率翅,就是把它編譯為虛擬數(shù)據(jù)庫(kù)引擎(VDBE)可讀的字節(jié)碼练俐。
對(duì)應(yīng)的函數(shù)聲明為:
int sqlite3_prepare_v2(
sqlite3 *db, /*數(shù)據(jù)庫(kù)句柄*/
const char *zSql, /*SQL文本,UTF-8編碼的*/
int nBytes, /*zSql的字節(jié)長(zhǎng)度*/
sqlite3_stmt **ppStmt, /*輸出:語(yǔ)句句柄*/
const char **pzTail /*輸出:指向zSql未使用部分的指針*/
)
說(shuō)明:
- sqlite3_prepare_v2() 只編譯zSql字符串中的第一個(gè)SQL語(yǔ)句(zSql字符串中可能包含多個(gè)SQL語(yǔ)句)冕臭。
- 然后分配這個(gè)語(yǔ)句執(zhí)行時(shí)所需的所有資源腺晾,并將其字節(jié)碼關(guān)聯(lián)到這個(gè)語(yǔ)句的句柄(也就是ppStmt參數(shù)指定的語(yǔ)句句柄)。
- ppStmt:語(yǔ)句的句柄ppStmt 依賴于所編譯的數(shù)據(jù)庫(kù)模式辜贵。如果在準(zhǔn)備或執(zhí)行語(yǔ)句期間悯蝉,模式改變,sqlite3_prepare_v2() 會(huì)自動(dòng)重新編譯語(yǔ)句托慨。若重新編譯失敗泉粉,就會(huì)在sqlite3_step()調(diào)用時(shí)返回SQLITE_SCHEMA錯(cuò)誤。
- pzTail:在調(diào)用sqlite3_prepare()后榴芳,pzTail會(huì)指向zSql字符串中的下一條語(yǔ)句的起始位置。使用pzTail跺撼,會(huì)使執(zhí)行一批SQL命令變得更容易窟感。
2、執(zhí)行
準(zhǔn)備就緒后歉井,下一步就是執(zhí)行sqlite3_step()柿祈,
聲明如下:
int sqlite3_step(sqlite3_stmt *pStmt);
說(shuō)明:
- sqlite3_step()接收的參數(shù)是sqlite3_prepare_v2()輸出的參數(shù)ppStmt。
- sqlite3_step()直接與VDBE通信哩至,執(zhí)行一個(gè)又一個(gè)字節(jié)碼指令來(lái)執(zhí)行SQL語(yǔ)句躏嚎。
- 在第一次調(diào)用sqlite3_step()時(shí),VDBE會(huì)獲取執(zhí)行命令所需的數(shù)據(jù)庫(kù)鎖菩貌。
- 對(duì)于不返回?cái)?shù)據(jù)的SQL語(yǔ)句卢佣,第一次sqlite3_step()后就執(zhí)行完SQL語(yǔ)句了,并返回一個(gè)指示結(jié)果的代碼箭阶。
- 對(duì)于返回?cái)?shù)據(jù)的SQL語(yǔ)句虚茶,如select語(yǔ)句戈鲁,第一次調(diào)用sqlite3_step()后,將語(yǔ)句定位在第一個(gè)記錄的B-tree游標(biāo)上嘹叫,后續(xù)調(diào)用sqlite3_step()會(huì)一次將光標(biāo)定位在結(jié)果集內(nèi)的后續(xù)記錄上婆殿,并返回SQLITE_ROW,直到返回SQLITE_DONE罩扇,表示游標(biāo)已到達(dá)結(jié)果集末尾婆芦。
3、完成與重置
語(yǔ)句執(zhí)行結(jié)束后喂饥,必須終止消约。可使用下面函數(shù)之一:
int sqlite3_finalize(sqlite3_stmt *pStmt);
int sqlite3_reset(sqlite3_stmt *pStmt);
說(shuō)明:
- sqlite3_finalize():關(guān)閉語(yǔ)句仰泻,釋放資源荆陆,提交或回滾任何隱式事務(wù),清除日志文件并釋放相關(guān)聯(lián)的鎖集侯。
- 若要重復(fù)使用語(yǔ)句被啼,可使用sqlite3_reset()。與sqlite3_finalize的差別在于棠枉,sqlite3_reset會(huì)保留與語(yǔ)句關(guān)聯(lián)的資源浓体,以便重新執(zhí)行,而不用再次調(diào)用sqlite3_prepare()來(lái)編譯SQL命令辈讶。
sqlite_complete():尋找字符串中的終止符:分號(hào)命浴。
三、獲取記錄
準(zhǔn)備查詢提供了獲取記錄信息的更多選擇贱除。
獲取結(jié)果集中的字段數(shù)生闲,函數(shù)聲明如下:
int sqlite3_column_count(sqlite_stmt *pStmt);
int sqlite3_data_count(sqlite3_stmt *pStmt);
說(shuō)明:
- sqlite3_column_count():返回與語(yǔ)句句柄關(guān)聯(lián)的字段數(shù)量;若語(yǔ)句不是select語(yǔ)句月幌,則返回0碍讯。
- 在sqlite3_step()返回SQLITE_ROW時(shí),返回當(dāng)前記錄的列數(shù)扯躺。只有語(yǔ)句句柄有有效的游標(biāo)時(shí)捉兴,才可以正常工作。
1录语、獲取列(字段)信息
獲取當(dāng)前記錄每一列的列名稱倍啥,函數(shù)聲明如下:
cont char *sqlite3_column_name(
sqlite3_stmt*, /*語(yǔ)句句柄*/
int iCol /*列的順序*/
)
獲取每個(gè)列的存儲(chǔ)類,函數(shù)聲明如下:
int sqlite3_column_type(
sqlite3_stmt*, /*語(yǔ)句句柄*/
int iCol /*列的順序*/
)
說(shuō)明:該函數(shù)返回五個(gè)存儲(chǔ)類對(duì)應(yīng)的整數(shù)值:
- #define SQLITE_INTEGER 1
- #define SQLITE_FLOAT 2
- #define SQLITE_TEXT 3
- #define SQLITE_BLOB 4
- #define SQLITE_NULL 5
獲取每個(gè)列聲明的數(shù)據(jù)類型澎埠,函數(shù)聲明如下:
const char *sqlite3_column_decltype(
sqlite3_stmt*, /*語(yǔ)句句柄*/
int iCol /*列的順序*/
)
說(shuō)明:
- 如果結(jié)果集中的列與實(shí)際表中的列不對(duì)應(yīng)(不對(duì)應(yīng)的例子如虽缕,結(jié)果集中的列是要返回一個(gè)文本值、表達(dá)式失暂、函數(shù)彼宠、聚合結(jié)果等鳄虱,而不是實(shí)際表中的列),那么這個(gè)函數(shù)就會(huì)返回其聲明類型為NULL凭峡。
獲得某一列的其他信息
const char *sqlite3_column_database_name(sqlite3_stmt *pStmt, int iCol);
const char *sqlite3_column_table_name(sqlite3_stmt *pStmt, int iCol);
const char *sqlite3_column_origin_name(sqlite3_stmt *pStmt, int iCol);
說(shuō)明:
- sqlite3_column_database_name:返回與這個(gè)列相關(guān)的數(shù)據(jù)庫(kù)
- sqlite3_column_table_name:返回與這個(gè)列相關(guān)的表
- sqlite3_column_origin_name:返回在schema中定義的實(shí)際名稱(別名等)
- 這些函數(shù)只有在編譯SQLITE時(shí)拙已,啟用了SQLITE_ENABLE_COLUMN_METADATA預(yù)處理命令時(shí)才能用。
2摧冀、獲取列(字段)值
獲取當(dāng)前記錄每列的值:
xxx sqlite3_column_xxx(
sqlite3_stmt*, /*語(yǔ)句句柄*/
int iCol /*列的順序*/
)
說(shuō)明:
- 該函數(shù)會(huì)按按照期望的數(shù)據(jù)類型返回列的值:
int sqlite3_column_int(sqlite3_stmt*, int iCol);
double sqlite3_column_double(sqlite3_stmt*, int iCol);
long long int sqlite3_column_int64(sqlite3_stmt*, int iCol);
const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);
const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);
const void *sqlite3_column_text16(sqlite3_stmt*, int iCol);
SQLite會(huì)將內(nèi)部數(shù)據(jù)類型表示形式轉(zhuǎn)換為所請(qǐng)求的類型:
內(nèi)部類型 | 請(qǐng)求類型 | 轉(zhuǎn)換 |
---|---|---|
NULL | INTEGER | 0 |
NULL | FLOAT | 0.0 |
NULL | TEXT | NULL |
NULL | BLOB | NULL |
INTEGER | FLOAT | 整型轉(zhuǎn)浮點(diǎn)型 |
INTEGER | TEXT | 整數(shù)的ASCII描述 |
INTEGER | BLOB | 整數(shù)的ASCII描述 |
FLOAT | INTEGER | 浮點(diǎn)型轉(zhuǎn)整型 |
FLOAT | TEXT | 浮點(diǎn)數(shù)的ASCII描述 |
FLOAT | BLOB | 浮點(diǎn)數(shù)的ASCII描述 |
TEXT | INTEGER | 使用atoi() |
TEXT | FLOAT | 使用atoi() |
TEXT | BLOB | 無(wú)變化 |
BLOB | INTEGER | 先轉(zhuǎn)成文本倍踪,再使用atoi() |
BLOB | FLOAT | 先轉(zhuǎn)成文本,再使用atoi() |
BLOB | TEXT | 需要時(shí)加上\0000終結(jié)符 |
獲取實(shí)際數(shù)據(jù)的長(zhǎng)度索昂,聲明如下
int sqlite3_column_bytes(
sqlite3_stmt*, /*語(yǔ)句句柄*/
int iCol /*列的順序*/
)
說(shuō)明:
- 獲取到長(zhǎng)度以后就可以使用sqlite3_column_blob()復(fù)制二進(jìn)制數(shù)據(jù)建车。
獲取連接句柄
int sqlite3_db_handle(sqlite3_stmt*);
說(shuō)明:
- sqlite3_errmsg()需要用到連接句柄
四、參數(shù)化查詢
1椒惨、默認(rèn)的參數(shù)順序
API支持在SQL語(yǔ)句中指定參數(shù)缤至,允許在后面為參數(shù)提供或綁定值。
參數(shù)化語(yǔ)句如下:
insert into episodes (id, name) values (?, ?)
說(shuō)明:
-
sqlite3_prepare()
識(shí)別到SQL語(yǔ)句中有參數(shù)康谆。內(nèi)部领斥,為每個(gè)參數(shù)分配一個(gè)編號(hào)來(lái)唯一標(biāo)識(shí)參數(shù)。 - 然后期望在執(zhí)行前沃暗,對(duì)給定的參數(shù)綁定特定的值月洛。
- 若沒有綁定值給參數(shù),
sqlite3_step()
會(huì)使用null來(lái)代替孽锥。
綁定參數(shù)值的函數(shù)聲明如下:
sqlite3_bind_xxx(
sqlite3_stmt*, /*語(yǔ)句句柄*/
int i, /*參數(shù)編號(hào)*/
xxx value /*要綁定的值*/
)
常用綁定函數(shù)如下:
int sqlite3_bind_int(sqlite3_stmt*, int, int);
int sqlite3_bind_double(sqlite3_stmt*, int, double);
int sqlite3_bind_int64(sqlite3_stmt*, int, long long int);
int sqlite3_bind_null(sqlite3_stmt*, int);
int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
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*));
說(shuō)明:
- 綁定函數(shù)分為兩類嚼黔,一類是標(biāo)量值(int, double, int64, 和 NULL),一類是數(shù)組(blob, text, 和 text16)
- 標(biāo)量值綁定和數(shù)組綁定的區(qū)別在于惜辑,后者需要一個(gè)長(zhǎng)度參數(shù)和一個(gè)指向清理函數(shù)的指針唬涧。
-
sqlite3_bind_text()
會(huì)自動(dòng)轉(zhuǎn)義引號(hào)字符
使用BLOB數(shù)組綁定函數(shù),聲明如下:
int sqlite3_bind_blob(
sqlite3_stmt*, /* 語(yǔ)句句柄 */
int, /* 順序 */
const void*, /* 指向blob數(shù)據(jù)的指針 */
int n, /* 數(shù)據(jù)的字節(jié)長(zhǎng)度 */
void(*)(void*) /* 清理處理程序 */
);
說(shuō)明:
最后一個(gè)參數(shù)盛撑,也就是清理句柄
(1)有兩個(gè)預(yù)定義的值爵卒,定義如下:
#define SQLITE_STATIC ((void(*)(void *))0)
#define SQLITE_TRANSIENT ((void(*)(void *))-1)
- SQLITE_STATIC:告訴數(shù)組綁定函數(shù),數(shù)組內(nèi)存駐留在非托管的控件撵彻,SQLite不會(huì)試圖清理該控件
- SQLITE_TRANSIENT告訴綁定數(shù)組,數(shù)組內(nèi)存常有變化实牡,SQLite需要使用自己的數(shù)據(jù)副本陌僵,該副本在語(yǔ)句終止時(shí)會(huì)自動(dòng)清除。
(2)還有一個(gè)指向自己的清理函數(shù)的指針创坞,函數(shù)形式如下:
void cleanup_fn(void*)
語(yǔ)句結(jié)束時(shí)碗短,SQLite會(huì)調(diào)用該清理函數(shù),并將數(shù)組內(nèi)存?zhèn)魅搿?/p>
2题涨、參數(shù)編號(hào)
給參數(shù)編號(hào)偎谁,而不是使用內(nèi)部序列編號(hào)总滩。參數(shù)編號(hào)的語(yǔ)法是問號(hào)后緊跟一個(gè)數(shù)字。
參考例子:
insert into episodes (id, cid, name) values (?100,?100,?101)";
說(shuō)明:
- 參數(shù)編號(hào)100使用兩次巡雨,表示需要將值綁定到多個(gè)地方闰渔,這樣可以節(jié)省時(shí)間。
- 參數(shù)編號(hào)的范圍是整數(shù)值1~999铐望。盡量選擇較小的數(shù)字
3冈涧、參數(shù)命名
給參數(shù)命名,在指定參數(shù)編號(hào)的地方指定一個(gè)名稱正蛙。
區(qū)別在于督弓,參數(shù)編號(hào)的語(yǔ)法是個(gè)問號(hào)?前綴乒验,而參數(shù)命名的前綴是一個(gè)冒號(hào)或者@符號(hào)愚隧。
示例如下:
insert into episodes (id, cid, name) values (:cosmo,:cosmo,@newman)
4、Tcl參數(shù)
基本與參數(shù)命名完全相同锻全,只是Tcl參數(shù)使用一些變量作為參數(shù)名稱狂塘。
Tcl參數(shù)語(yǔ)法,與命名參數(shù)的區(qū)別在于虱痕,不是前面的參數(shù)加上冒號(hào)(:)或@符號(hào)睹耐,而是使用美元符號(hào)($)。
五部翘、錯(cuò)誤與異常
一定要在代碼中關(guān)注的情況:
- 錯(cuò)誤
- 繁忙情況
- 模式更改
1硝训、錯(cuò)誤處理
API函數(shù),會(huì)返回整數(shù)結(jié)果碼新思,這些結(jié)果碼表示返回某種類型的錯(cuò)誤代碼窖梁。編程時(shí),必須確保處理了各種可能的錯(cuò)誤情況夹囚。
可以返回結(jié)果碼的函數(shù)有:
- sqlite3_bind_xxx()
- sqlite3_close()
- sqlite3_create_collation()
- sqlite3_collation_needed()
- sqlite3_create_function()
- sqlite3_prepare_v2() *
- sqlite3_exec() *
- sqlite3_finalize()
- sqlite3_get_table()
- sqlite3_open_v2() *
- sqlite3_reset()
- sqlite3_step()
說(shuō)明:標(biāo)*的是常見的需要關(guān)注返回結(jié)果碼的函數(shù)
可以使用sqlite3_errmsg()
獲取給定的錯(cuò)誤的詳細(xì)信息纵刘,聲明如下:
const char *sqlite3_errmsg(sqlite3*);
說(shuō)明:
- 參數(shù)為連接句柄。
- 返回連接上API調(diào)用產(chǎn)生的最近的錯(cuò)誤荸哟。
-
沒有錯(cuò)誤假哎,返回“not an error”.
2、繁忙情況處理
當(dāng)調(diào)用需要獲取鎖的API鞍历,但是SQLite無(wú)法得到鎖時(shí)舵抹,會(huì)返回SQLITE_BUSY。
處理這種情況的方法有三種:
- 通過重新運(yùn)行該語(yǔ)句劣砍,或者采取一些其他操作來(lái)自己處理SQLITE_BUSY惧蛹;
- 讓SQLite調(diào)用繁忙處理程序;
- 讓SQLite等待(阻塞或睡眠)一段時(shí)間來(lái)等待鎖解除。
2.1香嗓、用戶自定義的繁忙處理
函數(shù)聲明如下:
int sqlite3_busy_handler(
sqlite3*,
int(*)(void*,int),
void*
);
說(shuō)明:
- 第二個(gè)參數(shù):指向繁忙處理函數(shù)的函數(shù)指針迅腔。而繁忙處理函數(shù)的第二個(gè)參數(shù)是事先想同一個(gè)鎖事件的處理程序的調(diào)用次數(shù)。
- 第三個(gè)參數(shù):指向應(yīng)用程序特定數(shù)據(jù)的指針靠娱,會(huì)作為繁忙處理函數(shù)的第一個(gè)參數(shù)沧烈。
- 繁忙處理函數(shù)并不一定保證被調(diào)用,如果sqlite檢測(cè)到可能產(chǎn)生死鎖饱岸,就會(huì)放棄調(diào)用繁忙處理程序掺出。
- 唯一局限:繁忙處理程序可能不會(huì)關(guān)閉數(shù)據(jù)庫(kù)。因?yàn)槿绻P(guān)閉數(shù)據(jù)庫(kù)苫费,會(huì)刪除外面的執(zhí)行查詢的關(guān)鍵數(shù)據(jù)結(jié)構(gòu)汤锨,并導(dǎo)致程序崩潰。
3百框、模式改變處理
在sqlite3_prepare()和sqlite3_step()之間闲礼,發(fā)生模式更改發(fā)生了。
這種情況發(fā)生時(shí)铐维,唯一應(yīng)對(duì)的方法是處理改變柬泽,并重新開始。因?yàn)橐丫幾g的VDBE可能會(huì)指向一個(gè)已經(jīng)不存在的或者位置發(fā)生改變的數(shù)據(jù)庫(kù)對(duì)象嫁蛇。
可能會(huì)導(dǎo)致SQLITE_SCHEMA錯(cuò)誤:
- 分離數(shù)據(jù)庫(kù)锨并;
- 修改或安裝用戶自定義的函數(shù)或聚合;
- 修改或安裝用戶自定義的排序規(guī)則睬棚;
- 修改或安裝授權(quán)函數(shù)第煮;
- 清理數(shù)據(jù)庫(kù)空間;
跟蹤SQL語(yǔ)句執(zhí)行的操作:
void *sqlite3_trace(
sqlite3*,
void(*xTrace)(void*,const char*),
void*
);
六抑党、操作控制
API提供一些函數(shù)包警,在編譯或運(yùn)行時(shí)監(jiān)視或管理SQL命令。
1底靠、提交鉤子
監(jiān)視給定連接上的事務(wù)提交事件害晦,聲明如下:
void *sqlite3_commit_hook(
sqlite3 *cnx, /* 數(shù)據(jù)庫(kù)句柄 */
int(*xCallback)(void *data), /* 回調(diào)函數(shù) */
void *data /* 應(yīng)用程序數(shù)據(jù) */
);
說(shuō)明:
- 當(dāng)連接cnx上發(fā)生提交事務(wù)時(shí),觸發(fā)xCallback回調(diào)函數(shù)暑中;
- data為回調(diào)函數(shù)xCallback的參數(shù)
- 如果xCallback返回非零值壹瘟,提交將轉(zhuǎn)為回滾
- xCallback中傳入NULL,會(huì)禁用當(dāng)前注冊(cè)函數(shù)鳄逾;
- 一個(gè)連接只能注冊(cè)一個(gè)回調(diào)函數(shù)俐筋,如果沒有注冊(cè)過,sqlite3_commit_hook會(huì)返回NULL严衬。如果以前注冊(cè)過,會(huì)返回以前參數(shù)data值笆呆。
2请琳、回滾鉤子
監(jiān)視給定連接上的回滾事件粱挡,聲明如下:
void *sqlite3_rollback_hook(
sqlite3 *cnx,
void(*xCallback)(void *data),
void *data
);
3、更新鉤子
監(jiān)視給定連接上的所有更新俄精、插入询筏、刪除操作,聲明如下:
void *sqlite3_update_hook(
sqlite3 *cnx,
void(*)(void *, int, char const*, char const*, sqlite_int64),
void *data
);
其中第二個(gè)參數(shù)竖慧,也就是回調(diào)函數(shù)的聲明如下:
void callback (
void * data,
int operation_code,
char const *db_name,
char const *table_name,
sqlite_int64 rowid
),
說(shuō)明:
- data為sqlite3_update_hook的第三個(gè)參數(shù)嫌套;
- operation_code:代表插入、更新圾旨、刪除操作踱讨;
- db_name和table_name分別代表數(shù)據(jù)庫(kù)名和表名;
- rowid為受影響的行砍的;
- 系統(tǒng)表上的操作不會(huì)調(diào)用回調(diào)函數(shù)痹筛。
4、授權(quán)函數(shù)
監(jiān)控或控制查詢語(yǔ)句的編譯廓鞠,提供了一種限制某種SQL操作或否決對(duì)數(shù)據(jù)庫(kù)中特定表或字段訪問的方法:
int sqlite3_set_authorizer(
sqlite3*,
int (*xAuth)( void*,int,
const char*, const char*,
const char*,const char*),
void *pUserData
);
授權(quán)函數(shù)的形式如下:
int auth(
void*, /* user data */
int, /* event code */
const char*, /* event specific */
const char*, /* event specific */
const char*, /* database name */
const char* /* trigger or view name */
);
auth各參數(shù)的說(shuō)明:
- 第一個(gè)參數(shù)帚稠,是sqlite3_set_authorizer的第一個(gè)參數(shù)傳來(lái)的
- 第二個(gè)參數(shù),是表6-3中的某個(gè)常量床佳,代表授予的操作權(quán)限的類型
- 第三滋早、四個(gè)參數(shù),是具體的事件代碼砌们,在表6-2中
- 第五個(gè)參數(shù)杆麸,是數(shù)據(jù)庫(kù)名稱
- 第六個(gè)參數(shù),是負(fù)責(zé)訪問嘗試的最內(nèi)層的觸發(fā)器或視圖怨绣。為null角溃,代表訪問直接來(lái)自頂級(jí)的SQL語(yǔ)句。
-
返回值為SQLITE_OK篮撑、SQLITE_DENY,减细、 SQLITE_IGNORE中的一個(gè)。
終止給定連接上的懸掛數(shù)據(jù)庫(kù)操作:
void sqlite3_interrupt(
sqlite3* /* 連接句柄 */
);
按組合鍵Ctrl+C時(shí)會(huì)調(diào)用這個(gè)函數(shù)
讓應(yīng)用程序在長(zhǎng)時(shí)間運(yùn)行的查詢過程中為用戶提供反饋信息:
void sqlite3_progress_handler(
sqlite3*, /* 連接句柄 */
int frq, /* 調(diào)用頻率 */
int(*)(void*), /* 回調(diào)函數(shù) */
void* /* 應(yīng)用程序數(shù)據(jù) */
);
七赢笨、線程
1未蝌、共享緩存模型
- 允許一個(gè)進(jìn)程中的多個(gè)連接使用共同的緩存和不同的并發(fā)模型。
- 這個(gè)圖是為嵌入式服務(wù)器設(shè)計(jì)的茧妒,這個(gè)服務(wù)器中的單線程可以代表其他多個(gè)線程有效的管理多個(gè)數(shù)據(jù)庫(kù)連接萧吠。
- 線程向服務(wù)器中發(fā)送SQL語(yǔ)句,服務(wù)器使用分配給該線程的連接來(lái)執(zhí)行桐筏,并把結(jié)果回傳給線程纸型。
- 線程可以發(fā)起命令,控制自己的事務(wù),只是其實(shí)際的連接狰腌,存在于另一個(gè)線程(服務(wù)器線程)中除破,被服務(wù)器線程管理著。
-
共享緩存模式使用表鎖琼腔,分別保持讀連接和寫連接瑰枫。表鎖只存在于共享緩存下的連接。
共享緩存模式中的連接使用的不同并發(fā)模型和隔離級(jí)別:
- 讀提交隔離級(jí)別:連接不可以想已有讀鎖連接的表中寫入丹莲。
- 讀未提交隔離級(jí)別:連接不會(huì)在讀取的表上加讀鎖光坝,因此寫操作可以在連接讀取時(shí)修改表。
- 解鎖通知:
2甥材、線程和內(nèi)存管理
與線程和內(nèi)存管理相關(guān)聯(lián)的函數(shù):
void sqlite3_soft_heap_limit(int N);
int sqlite3_release_memory(int N);
說(shuō)明:
- sqlite3_soft_heap_limit:將調(diào)用線程的當(dāng)前軟堆設(shè)置為N字節(jié)
- sqlite3_release_memory:當(dāng)使用中線程的堆超過N字節(jié)時(shí)盯另,會(huì)調(diào)用sqlite3_release_memory。返回值為實(shí)際釋放的字節(jié)數(shù)擂达。