配置使用sqlite
一.使用流程
要使用sqlite,需要從sqlite官網(wǎng)下載到三個(gè)文件,分別為sqlite3.lib,sqlite3.dll,sqlite3.h,然后再在自己的工程中配置好頭文件和庫(kù)文件,同時(shí)將dll文件放到當(dāng)前目錄下,就完成配置可以使用sqlite了。
使用的過(guò)程根據(jù)使用的函數(shù)大致分為如下幾個(gè)過(guò)程:
sqlite3_open()sqlite3_prepare()sqlite3_step()sqlite3_column()sqlite3_finalize()sqlite3_close()
這幾個(gè)過(guò)程是概念上的說(shuō)法,而不完全是程序運(yùn)行的過(guò)程,如sqlite3_column()表示的是對(duì)查詢(xún)獲得一行里面的數(shù)據(jù)的列的各個(gè)操作統(tǒng)稱(chēng),實(shí)際上在sqlite中并不存在這個(gè)函數(shù)。
1.??sqlite3_open():打開(kāi)數(shù)據(jù)庫(kù)
在操作數(shù)據(jù)庫(kù)之前,首先要打開(kāi)數(shù)據(jù)庫(kù)。這個(gè)函數(shù)打開(kāi)一個(gè)sqlite數(shù)據(jù)庫(kù)文件的連接并且返回一個(gè)數(shù)據(jù)庫(kù)連接對(duì)象。這個(gè)操作同時(shí)程序中的第一個(gè)調(diào)用的sqlite函數(shù),同時(shí)也是其他sqlite api的先決條件。許多的sqlite接口函數(shù)都需要一個(gè)數(shù)據(jù)庫(kù)連接對(duì)象的指針作為它們的第一個(gè)參數(shù)。
函數(shù)定義
int sqlite3_open(
??const char *filename,???/* Database filename (UTF-8) */
??sqlite3 **ppDb??????????/* OUT: SQLite db handle */
);
int sqlite3_open16(
??const void *filename,???/* Database filename (UTF-16) */
??sqlite3 **ppDb??????????/* OUT: SQLite db handle */
);
int sqlite3_open_v2(
??const char *filename,???/* Database filename (UTF-8) */
??sqlite3 **ppDb,?????????/* OUT: SQLite db handle */
??int flags,??????????????/* Flags */
??const char *zVfs????????/* Name of VFS module to use */
);
?
說(shuō)明:
假如這個(gè)要被打開(kāi)的數(shù)據(jù)文件不存在,則一個(gè)同名的數(shù)據(jù)庫(kù)文件將被創(chuàng)建。如果使用sqlite3_open和sqlite3_open_v2的話(huà),數(shù)據(jù)庫(kù)將采用UTF-8的編碼方式,sqlite3_open16采用UTF-16的編碼方式
返回值:
如果sqlite數(shù)據(jù)庫(kù)被成功打開(kāi)(或創(chuàng)建),將會(huì)返回SQLITE_OK,否則將會(huì)返回錯(cuò)誤碼。Sqlite3_errmsg()或者sqlite3_errmsg16可以用于獲得數(shù)據(jù)庫(kù)打開(kāi)錯(cuò)誤碼的英文描述,這兩個(gè)函數(shù)定義為:
const char *sqlite3_errmsg(sqlite3*);
const void *sqlite3_errmsg16(sqlite3*);
????????
參數(shù)說(shuō)明:
filename:需要被打開(kāi)的數(shù)據(jù)庫(kù)文件的文件名,在sqlite3_open和sqlite3_open_v2中這個(gè)參數(shù)采用UTF-8編碼,而在sqlite3_open16中則采用UTF-16編碼
ppDb:一個(gè)數(shù)據(jù)庫(kù)連接句柄被返回到這個(gè)參數(shù),即使發(fā)生錯(cuò)誤。唯一的一場(chǎng)是如果sqlite不能分配內(nèi)存來(lái)存放sqlite對(duì)象,ppDb將會(huì)被返回一個(gè)NULL值。
flags:作為數(shù)據(jù)庫(kù)連接的額外控制的參數(shù),可以是SQLITE_OPEN_READONLY,SQLITE_OPEN_READWRITE和SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE中的一個(gè),用于控制數(shù)據(jù)庫(kù)的打開(kāi)方式,可以和SQLITE_OPEN_NOMUTEX,SQLITE_OPEN_FULLMUTEX,?SQLITE_OPEN_SHAREDCACHE,以及SQLITE_OPEN_PRIVATECACHE結(jié)合使用,具體的詳細(xì)情況可以查閱文檔
?
?
?
?
2.??Sqlite3_prepare()
這個(gè)函數(shù)將sql文本轉(zhuǎn)換成一個(gè)準(zhǔn)備語(yǔ)句(prepared statement)對(duì)象,同時(shí)返回這個(gè)對(duì)象的指針。這個(gè)接口需要一個(gè)數(shù)據(jù)庫(kù)連接指針以及一個(gè)要準(zhǔn)備的包含SQL語(yǔ)句的文本。它實(shí)際上并不執(zhí)行(evaluate)這個(gè)SQL語(yǔ)句,它僅僅為執(zhí)行準(zhǔn)備這個(gè)sql語(yǔ)句
函數(shù)定義(僅列出UTF-8的)
int sqlite3_prepare(
??sqlite3 *db,????????????/* Database handle */
??const char *zSql,???????/* SQL statement, UTF-8 encoded */
??int nByte,??????????????/* Maximum length of zSql in bytes. */
??sqlite3_stmt **ppStmt,??/* OUT: Statement handle */
??const char **pzTail?????/* OUT: Pointer to unused portion of zSql */
);
int sqlite3_prepare_v2(
??sqlite3 *db,????????????/* Database handle */
??const char *zSql,???????/* SQL statement, UTF-8 encoded */
??int nByte,??????????????/* Maximum length of zSql in bytes. */
??sqlite3_stmt **ppStmt,??/* OUT: Statement handle */
??const char **pzTail?????/* OUT: Pointer to unused portion of zSql */
);
?
參數(shù):
db:數(shù)據(jù)指針
zSql:sql語(yǔ)句,使用UTF-8編碼
nByte:如果nByte小于0,則函數(shù)取出zSql中從開(kāi)始到第一個(gè)0終止符的內(nèi)容;如果nByte不是負(fù)的,那么它就是這個(gè)函數(shù)能從zSql中讀取的字節(jié)數(shù)的最大值。如果nBytes非負(fù),zSql在第一次遇見(jiàn)’/000/或’u000’的時(shí)候終止
pzTail:上面提到zSql在遇見(jiàn)終止符或者是達(dá)到設(shè)定的nByte之后結(jié)束,假如zSql還有剩余的內(nèi)容,那么這些剩余的內(nèi)容被存放到pZTail中,不包括終止符
ppStmt:能夠使用sqlite3_step()執(zhí)行的編譯好的準(zhǔn)備語(yǔ)句的指針,如果錯(cuò)誤發(fā)生,它被置為NULL,如假如輸入的文本不包括sql語(yǔ)句。調(diào)用過(guò)程必須負(fù)責(zé)在編譯好的sql語(yǔ)句完成使用后使用sqlite3_finalize()刪除它。
?
說(shuō)明
如果執(zhí)行成功,則返回SQLITE_OK,否則返回一個(gè)錯(cuò)誤碼。推薦在現(xiàn)在任何的程序中都使用sqlite3_prepare_v2這個(gè)函數(shù),sqlite3_prepare只是用于前向兼容
?
備注
typedef struct sqlite3_stmt sqlite3_stmt;
????????
準(zhǔn)備語(yǔ)句(prepared statement)對(duì)象一個(gè)代表一個(gè)簡(jiǎn)單SQL語(yǔ)句對(duì)象的實(shí)例,這個(gè)對(duì)象通常被稱(chēng)為“準(zhǔn)備語(yǔ)句”或者“編譯好的SQL語(yǔ)句”或者就直接稱(chēng)為“語(yǔ)句”。
?????????語(yǔ)句對(duì)象的生命周期經(jīng)歷這樣的過(guò)程:
l??使用sqlite3_prepare_v2或相關(guān)的函數(shù)創(chuàng)建這個(gè)對(duì)象
l??使用sqlite3_bind_*()給宿主參數(shù)(host parameters)綁定值
l??通過(guò)調(diào)用sqlite3_step一次或多次來(lái)執(zhí)行這個(gè)sql
l??使用sqlite3——reset()重置這個(gè)語(yǔ)句,然后回到第2步,這個(gè)過(guò)程做0次或多次
l??使用sqlite3_finalize()銷(xiāo)毀這個(gè)對(duì)象
?
在sqlite中并沒(méi)有定義sqlite3_stmt這個(gè)結(jié)構(gòu)的具體內(nèi)容,它只是一個(gè)抽象類(lèi)型,在使用過(guò)程中一般以它的指針進(jìn)行操作,而sqlite3_stmt類(lèi)型的指針在實(shí)際上是一個(gè)指向Vdbe的結(jié)構(gòu)體得指針
在傳給sqlite3_prepare_v2()的sql的語(yǔ)句文本或者它的變量中,滿(mǎn)足如下模板的文字將被替換成一個(gè)參數(shù):
l???
l???NNN,NNN代表數(shù)字
l??:VVV,VVV代表字符
l??@VVV
l??$VVV
在上面這些模板中,NNN代表一個(gè)數(shù)字,VVV代表一個(gè)字母數(shù)字標(biāo)記符(例如:222表示名稱(chēng)為222的標(biāo)記符),sql語(yǔ)句中的參數(shù)(變量)通過(guò)上面的幾個(gè)模板來(lái)指定,如
“select ? from ? “這個(gè)語(yǔ)句中指定了兩個(gè)參數(shù),sqlite語(yǔ)句中的第一個(gè)參數(shù)的索引值是1,這就知道這個(gè)語(yǔ)句中的兩個(gè)參數(shù)的索引分別為1和2,使用”?”的話(huà)會(huì)被自動(dòng)給予索引值,而使用”?NNN”則可以自己指定參數(shù)的索引值,它表示這個(gè)參數(shù)的索引值為NNN。”:VVV”表示一個(gè)名為”VVV”的參數(shù),它也有一個(gè)索引值,被自動(dòng)指定。
可以使用sqlite3_bind_*()來(lái)給這些參數(shù)綁定值
?
?
?
3.??sqlite3_setp()
這個(gè)過(guò)程用于執(zhí)行有前面sqlite3_prepare創(chuàng)建的準(zhǔn)備語(yǔ)句。這個(gè)語(yǔ)句執(zhí)行到結(jié)果的第一行可用的位置。繼續(xù)前進(jìn)到結(jié)果的第二行的話(huà),只需再次調(diào)用sqlite3_setp()。繼續(xù)調(diào)用sqlite3_setp()知道這個(gè)語(yǔ)句完成,那些不返回結(jié)果的語(yǔ)句(如:INSERT,UPDATE,或DELETE),sqlite3_step()只執(zhí)行一次就返回
函數(shù)定義
int sqlite3_step(sqlite3_stmt*);
返回值
函數(shù)的返回值基于創(chuàng)建sqlite3_stmt參數(shù)所使用的函數(shù),假如是使用老版本的接口sqlite3_prepare()和sqlite3_prepare16(),返回值會(huì)是?SQLITE_BUSY,?SQLITE_DONE,?SQLITE_ROW,?SQLITE_ERROR?或?SQLITE_MISUSE,而v2版本的接口sqlite3_prepare_v2()和sqlite3_prepare16_v2()則會(huì)同時(shí)返回這些結(jié)果碼和擴(kuò)展結(jié)果碼。
對(duì)所有V3.6.23.1以及其前面的所有版本,需要在sqlite3_step()之后調(diào)用sqlite3_reset(),在后續(xù)的sqlite3_ step之前。如果調(diào)用sqlite3_reset重置準(zhǔn)備語(yǔ)句失敗,將會(huì)導(dǎo)致sqlite3_ step返回SQLITE_MISUSE,但是在V3. 6.23.1以后,sqlite3_step()將會(huì)自動(dòng)調(diào)用sqlite3_reset。
int sqlite3_reset(sqlite3_stmt *pStmt);
sqlite3_reset用于重置一個(gè)準(zhǔn)備語(yǔ)句對(duì)象到它的初始狀態(tài),然后準(zhǔn)備被重新執(zhí)行。所有sql語(yǔ)句變量使用sqlite3_bind*綁定值,使用sqlite3_clear_bindings重設(shè)這些綁定。Sqlite3_reset接口重置準(zhǔn)備語(yǔ)句到它代碼開(kāi)始的時(shí)候。sqlite3_reset并不改變?cè)跍?zhǔn)備語(yǔ)句上的任何綁定值,那么這里猜測(cè),可能是語(yǔ)句在被執(zhí)行的過(guò)程中發(fā)生了其他的改變,然后這個(gè)語(yǔ)句將它重置到綁定值的時(shí)候的那個(gè)狀態(tài)。
?
4.??sqlite3_column()
這個(gè)過(guò)程從執(zhí)行sqlite3_step()執(zhí)行一個(gè)準(zhǔn)備語(yǔ)句得到的結(jié)果集的當(dāng)前行中返回一個(gè)列。每次sqlite3_step得到一個(gè)結(jié)果集的列停下后,這個(gè)過(guò)程就可以被多次調(diào)用去查詢(xún)這個(gè)行的各列的值。對(duì)列操作是有多個(gè)函數(shù),均以sqlite3_column為前綴
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);
double sqlite3_column_double(sqlite3_stmt*, int iCol);
int sqlite3_column_int(sqlite3_stmt*, int iCol);
sqlite3_int64 sqlite3_column_int64(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_value *sqlite3_column_value(sqlite3_stmt*, int iCol);
說(shuō)明
第一個(gè)參數(shù)為從sqlite3_prepare返回來(lái)的prepared statement對(duì)象的指針,第二參數(shù)指定這一行中的想要被返回的列的索引。最左邊的一列的索引號(hào)是0,行的列數(shù)可以使用sqlite3_colum_count()獲得。
這些過(guò)程會(huì)根據(jù)情況去轉(zhuǎn)換數(shù)值的類(lèi)型,sqlite內(nèi)部使用sqlite3_snprintf()去自動(dòng)進(jìn)行這個(gè)轉(zhuǎn)換,下面是關(guān)于轉(zhuǎn)換的細(xì)節(jié)表:
內(nèi)部類(lèi)型
請(qǐng)求的類(lèi)型
轉(zhuǎn)換
NULL
INTEGER
結(jié)果是0
NULL
FLOAT
結(jié)果是0.0
NULL
TEXT
結(jié)果是NULL
NULL
BLOB
結(jié)果是NULL
INTEGER
FLOAT
從整形轉(zhuǎn)換到浮點(diǎn)型
INTEGER
TEXT
整形的ASCII碼顯示
INTEGER
BLOB
同上
FLOAT
INTEGER
浮點(diǎn)型轉(zhuǎn)換到整形
FLOAT
TEXT
浮點(diǎn)型的ASCII顯示
FLOAT
BLOB
同上
TEXT
INTEGER
使用atoi()
TEXT
FLOAT
使用atof()
TEXT
BLOB
沒(méi)有轉(zhuǎn)換
BLOB
INTEGER
先到TEXT,然后使用atoi
BLOB
FLOAT
先到TEXT,然后使用atof
BLOB
TEXT
如果需要的話(huà)添加0終止符
?
注:BLOB數(shù)據(jù)類(lèi)型是指二進(jìn)制的數(shù)據(jù)塊,比如要在數(shù)據(jù)庫(kù)中存放一張圖片,這張圖片就會(huì)以二進(jìn)制形式存放,在sqlite中對(duì)應(yīng)的數(shù)據(jù)類(lèi)型就是BLOB
?
int sqlite3_column_bytes(sqlite3_stmt*, int iCol)int sqlite3_column_bytes16(sqlite3_stmt*, int iCol)兩個(gè)函數(shù)返回對(duì)應(yīng)列的內(nèi)容的字節(jié)數(shù),這個(gè)字節(jié)數(shù)不包括后面類(lèi)型轉(zhuǎn)換過(guò)程中加上的0終止符。
下面是幾個(gè)最安全和最簡(jiǎn)單的使用策略
先sqlite3_column_text()?,然后?sqlite3_column_bytes()先sqlite3_column_blob(),然后sqlite3_column_bytes()先sqlite3_column_text16(),然后sqlite3_column_bytes16()
?
?
5.??sqlite3_finalize
????int sqlite3_finalize(sqlite3_stmt *pStmt);
這個(gè)過(guò)程銷(xiāo)毀前面被sqlite3_prepare創(chuàng)建的準(zhǔn)備語(yǔ)句,每個(gè)準(zhǔn)備語(yǔ)句都必須使用這個(gè)函數(shù)去銷(xiāo)毀以防止內(nèi)存泄露。
在空指針上調(diào)用這個(gè)函數(shù)沒(méi)有什么影響,同時(shí)可以準(zhǔn)備語(yǔ)句的生命周期的任一時(shí)刻調(diào)用這個(gè)函數(shù):在語(yǔ)句被執(zhí)行前,一次或多次調(diào)用sqlite_reset之后,或者在sqlite3_step任何調(diào)用之后不管語(yǔ)句是否完成執(zhí)行
?
6.??sqlite3_close
這個(gè)過(guò)程關(guān)閉前面使用sqlite3_open打開(kāi)的數(shù)據(jù)庫(kù)連接,任何與這個(gè)連接相關(guān)的準(zhǔn)備語(yǔ)句必須在調(diào)用這個(gè)關(guān)閉函數(shù)之前被釋放
?
?
二.使用舉例
?
?#include "stdafx.h"
#include "sqlite3.h"
static
?int
?callback(
void
?*NotUsed,
int
?argc,
char
?**argv,
char
?**azColName)
{
????
int
?i;
????
for
(i=0; i<argc; i++){
???????
printf
(
"%s = %s/n"
, azColName[i], argv[i] ? argv[i] :
"NULL"
);
????
}
????
printf
(
"/n"
);
????
return
?0;
}
#define CHECK_RC(rc,szInfo,szErrMsg,db) if(rc!=SQLITE_OK) /
???????????
{
printf
(
"%s error!/n"
,szInfo);/
???????????
printf
(
"%s/n"
,szErrMsg);??? /
???????????
sqlite3_free(szErrMsg);???????? /
???????????
sqlite3_close(db);????????????? /
???????????
return
?0;}
int
?_tmain(
int
?argc, _TCHAR* argv[])
{
?
?????
sqlite3 *db;
????
char
?*dbPath=
"f:/test.db"
;
????
char
?*szErrMsg = 0;
?
?????
int
?rc= sqlite3_open(dbPath, &db);
????
CHECK_RC(rc,
"open database"
,db);
????
char
?*szSql=
"create table UserInfo(ID int primary key , UserName char, PassWord char);"
;
????
rc=sqlite3_exec(db,szSql,0,0,&szErrMsg);
????
CHECK_RC(rc,
"create table"
,szErrMsg,db);
????
rc=sqlite3_exec(db,
"insert into UserInfo(ID,UserName,PassWord) values(1,'kfqcome','123456')"
,0,0,&szErrMsg);
????
CHECK_RC(rc,
"insert info"
,szErrMsg,db);
????
rc=sqlite3_exec(db,
"insert into UserInfo(ID,UserName,PassWord) values(2,'miss wang','654321')"
,0,0,&szErrMsg);
????
CHECK_RC(rc,
"insert info"
,szErrMsg,db);
????
szSql=
"select * from UserInfo"
;
????
rc = sqlite3_exec(db,szSql, callback, 0, &szErrMsg);
????
CHECK_RC(rc,
"query values"
,szErrMsg,db);
????
sqlite3_close(db);
????
getchar
();
????
return
?0;
}
輸出的結(jié)果:
ID = 1
UserName = kfqcome
PassWord = 123456
?
ID = 2
UserName = miss wang
PassWord = 654321
?
這里執(zhí)行sql語(yǔ)句用的是sqlite3_exec,它是前面幾個(gè)函數(shù)的封裝
?
int sqlite3_exec(
??sqlite3*,??????????????????????????????????/* An open database */
??const char *sql,???????????????????????????/* SQL to be evaluated */
??int (*callback)(void*,int,char**,char**),??/* Callback function */
??void *,????????????????????????????????????/* 1st argument to callback */
??char **errmsg??????????????????????????????/* Error msg written here */
);
sqlite3_exec是sqlite3_prepare_v2,sqlite3_step()和sqlite3_finalize()的封裝,能讓程序多次執(zhí)行sql語(yǔ)句而不要寫(xiě)許多重復(fù)的代碼。
Sqlite3_exec接口執(zhí)行0或多個(gè)UTF-8編碼的,分號(hào)分割的sql語(yǔ)句,傳到第二個(gè)參數(shù)中。如果sqlite3_exec的第三個(gè)參數(shù)回調(diào)函數(shù)指針不為空,那么它會(huì)為每個(gè)來(lái)自執(zhí)行的SQL語(yǔ)句的結(jié)果行調(diào)用(也就是說(shuō)回調(diào)函數(shù)會(huì)調(diào)用多次,上面例子中會(huì)返回2個(gè)結(jié)果行,因而會(huì)被執(zhí)行2次),第4個(gè)參數(shù)是傳給回調(diào)函數(shù)的第一個(gè)參數(shù),如果回調(diào)函數(shù)指針為空,那么回調(diào)不會(huì)發(fā)生同時(shí)結(jié)果行被忽略。
如果在執(zhí)行sql語(yǔ)句中有錯(cuò)誤發(fā)生,那么當(dāng)前的語(yǔ)句的執(zhí)行被停止,后續(xù)的語(yǔ)句也被跳過(guò)。第五個(gè)參數(shù)不為空的時(shí)候,它被分配內(nèi)存并寫(xiě)入了錯(cuò)誤信息,所以在sqlite3_exec后面需要調(diào)用sqlite3_free去釋放這個(gè)對(duì)象以防止內(nèi)存泄露
?
回調(diào)函數(shù):
int (*callback)(void*,int,char**,char**),??/* Callback function */
?????????第一個(gè)參數(shù)通過(guò)sqlite3_exec的第第四個(gè)參數(shù)傳入的
?????????第二個(gè)參數(shù)是結(jié)果行的列數(shù)
?????????第三個(gè)參數(shù)是行中列數(shù)據(jù)的指針
?????????第四個(gè)參數(shù)是行中列名稱(chēng)的指針