sqlite3使用简介(内含解决sqlite内存的方法)
一.使用流程
要使用sqlite,需要從sqlite官網(wǎng)下載到三個文件,分別為sqlite3.lib,sqlite3.dll,sqlite3.h,然后再在自己的工程中配置好頭文件和庫文件,同時將dll文件放到當前目錄下,就完成配置可以使用sqlite了。
使用的過程根據(jù)使用的函數(shù)大致分為如下幾個過程:
- sqlite3_open()
- sqlite3_prepare()
- sqlite3_step()
- sqlite3_column()
- sqlite3_finalize()
- sqlite3_close()
這幾個過程是概念上的說法,而不完全是程序運行的過程,如sqlite3_column()表示的是對查詢獲得一行里面的數(shù)據(jù)的列的各個操作統(tǒng)稱,實際上在sqlite中并不存在這個函數(shù)。
1.? sqlite3_open():打開數(shù)據(jù)庫
在操作數(shù)據(jù)庫之前,首先要打開數(shù)據(jù)庫。這個函數(shù)打開一個sqlite數(shù)據(jù)庫文件的連接并且返回一個數(shù)據(jù)庫連接對象。這個操作同時程序中的第一個調(diào)用的 sqlite函數(shù),同時也是其他sqlite api的先決條件。許多的sqlite接口函數(shù)都需要一個數(shù)據(jù)庫連接對象的指針作為它們的第一個參數(shù)。
函數(shù)定義
? const char *filename,?? /* Database filename (UTF-8) */
? sqlite3 **ppDb????????? /* OUT: SQLite db handle */
);
? const void *filename,?? /* Database filename (UTF-16) */
? sqlite3 **ppDb????????? /* OUT: SQLite db handle */
);
? 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 */
);
?
說明:
假如這個要被打開的數(shù)據(jù)文件不存在,則一個同名的數(shù)據(jù)庫文件將被創(chuàng)建。如果使用sqlite3_open和sqlite3_open_v2的話,數(shù)據(jù)庫將采用UTF-8的編碼方式,sqlite3_open16采用UTF-16的編碼方式
返回值:
如果sqlite數(shù)據(jù)庫被成功打開(或創(chuàng)建),將會返回SQLITE_OK,否則將會返回錯誤碼。Sqlite3_errmsg()或者sqlite3_errmsg16可以用于獲得數(shù)據(jù)庫打開錯誤碼的英文描述,這兩個函數(shù)定義為:
const char *sqlite3_errmsg(sqlite3*);
const void *sqlite3_errmsg16(sqlite3*);
????????
參數(shù)說明:
filename:需要被打開的數(shù)據(jù)庫文件的文件名,在sqlite3_open和sqlite3_open_v2中這個參數(shù)采用UTF-8編碼,而在sqlite3_open16中則采用UTF-16編碼
ppDb:一個數(shù)據(jù)庫連接句柄被返回到這個參數(shù),即使發(fā)生錯誤。唯一的一場是如果sqlite不能分配內(nèi)存來存放sqlite對象,ppDb將會被返回一個NULL值。
flags:作為數(shù)據(jù)庫連接的額外控制的參數(shù),可以是SQLITE_OPEN_READONLY,SQLITE_OPEN_READWRITE和 SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE中的一個,用于控制數(shù)據(jù)庫的打開方式,可以和SQLITE_OPEN_NOMUTEX,SQLITE_OPEN_FULLMUTEX,?SQLITE_OPEN_SHAREDCACHE,以及SQLITE_OPEN_PRIVATECACHE結(jié)合使用,具體的詳細情況可以查閱文檔
?
?
?
?
2.? Sqlite3_prepare()
這個函數(shù)將sql文本轉(zhuǎn)換成一個準備語句(prepared statement)對象,同時返回這個對象的指針。這個接口需要一個數(shù)據(jù)庫連接指針以及一個要準備的包含SQL語句的文本。它實際上并不執(zhí)行(evaluate)這個SQL語句,它僅僅為執(zhí)行準備這個sql語句
函數(shù)定義(僅列出UTF-8的)
? 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 */
);
? 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語句,使用UTF-8編碼
nByte:如果nByte小于0,則函數(shù)取出zSql中從開始到第一個0終止符的內(nèi)容;如果nByte不是負的,那么它就是這個函數(shù)能從zSql中讀取的字節(jié)數(shù)的最大值。如果nBytes非負,zSql在第一次遇見’/000/或’u000’的時候終止
pzTail:上面提到zSql在遇見終止符或者是達到設(shè)定的nByte之后結(jié)束,假如zSql還有剩余的內(nèi)容,那么這些剩余的內(nèi)容被存放到pZTail中,不包括終止符
ppStmt:能夠使用sqlite3_step()執(zhí)行的編譯好的準備語句的指針,如果錯誤發(fā)生,它被置為NULL,如假如輸入的文本不包括sql語句。調(diào)用過程必須負責在編譯好的sql語句完成使用后使用sqlite3_finalize()刪除它。
?
說明
如果執(zhí)行成功,則返回SQLITE_OK,否則返回一個錯誤碼。推薦在現(xiàn)在任何的程序中都使用sqlite3_prepare_v2這個函數(shù),sqlite3_prepare只是用于前向兼容
?
備注
<1>準備語句(prepared statement)對象
typedef struct sqlite3_stmt sqlite3_stmt;
????????
準備語句(prepared statement)對象一個代表一個簡單SQL語句對象的實例,這個對象通常被稱為“準備語句”或者“編譯好的SQL語句”或者就直接稱為“語句”。
???????? 語句對象的生命周期經(jīng)歷這樣的過程:
l? 使用sqlite3_prepare_v2或相關(guān)的函數(shù)創(chuàng)建這個對象
l? 使用sqlite3_bind_*()給宿主參數(shù)(host parameters)綁定值
l? 通過調(diào)用sqlite3_step一次或多次來執(zhí)行這個sql
l? 使用sqlite3——reset()重置這個語句,然后回到第2步,這個過程做0次或多次
l? 使用sqlite3_finalize()銷毀這個對象
?
在sqlite中并沒有定義sqlite3_stmt這個結(jié)構(gòu)的具體內(nèi)容,它只是一個抽象類型,在使用過程中一般以它的指針進行操作,而sqlite3_stmt類型的指針在實際上是一個指向Vdbe的結(jié)構(gòu)體得指針
<2>宿主參數(shù)(host parameters)
在傳給sqlite3_prepare_v2()的sql的語句文本或者它的變量中,滿足如下模板的文字將被替換成一個參數(shù):
l? ?
l? ?NNN,NNN代表數(shù)字
l? :VVV,VVV代表字符
l? @VVV
l? $VVV
在上面這些模板中,NNN代表一個數(shù)字,VVV代表一個字母數(shù)字標記符(例如:222表示名稱為222的標記符),sql語句中的參數(shù)(變量)通過上面的幾個模板來指定,如
“select ? from ? “這個語句中指定了兩個參數(shù),sqlite語句中的第一個參數(shù)的索引值是1,這就知道這個語句中的兩個參數(shù)的索引分別為1和2,使用”?”的話會被自動給 予索引值,而使用”?NNN”則可以自己指定參數(shù)的索引值,它表示這個參數(shù)的索引值為NNN。”:VVV”表示一個名為”VVV”的參數(shù),它也有一個索引 值,被自動指定。
可以使用sqlite3_bind_*()來給這些參數(shù)綁定值
?
?
?
3.? sqlite3_setp()
這個過程用于執(zhí)行有前面sqlite3_prepare創(chuàng)建的準備語句。這個語句執(zhí)行到結(jié)果的第一行可用的位置。繼續(xù)前進到結(jié)果的第二行的話,只需再次調(diào) 用sqlite3_setp()。繼續(xù)調(diào)用sqlite3_setp()知道這個語句完成,那些不返回結(jié)果的語句(如:INSERT,UPDATE,或 DELETE),sqlite3_step()只執(zhí)行一次就返回
函數(shù)定義
int sqlite3_step(sqlite3_stmt*);
返回值
函數(shù)的返回值基于創(chuàng)建sqlite3_stmt參數(shù)所使用的函數(shù),假如是使用老版本的接口sqlite3_prepare()和 sqlite3_prepare16(),返回值會 是?SQLITE_BUSY,?SQLITE_DONE,?SQLITE_ROW,?SQLITE_ERROR 或?SQLITE_MISUSE,而v2版本的接口sqlite3_prepare_v2()和sqlite3_prepare16_v2()則會同時返 回這些結(jié)果碼和擴展結(jié)果碼。
對所有V3.6.23.1以及其前面的所有版本,需要在sqlite3_step()之后調(diào)用sqlite3_reset(),在后續(xù)的sqlite3_ step之前。如果調(diào)用sqlite3_reset重置準備語句失敗,將會導(dǎo)致sqlite3_ step返回SQLITE_MISUSE,但是在V3. 6.23.1以后,sqlite3_step()將會自動調(diào)用sqlite3_reset。
int sqlite3_reset(sqlite3_stmt *pStmt);
sqlite3_reset用于重置一個準備語句對象到它的初始狀態(tài),然后準備被重新執(zhí)行。所有sql語句變量使用sqlite3_bind*綁定值,使 用sqlite3_clear_bindings重設(shè)這些綁定。Sqlite3_reset接口重置準備語句到它代碼開始的時候。sqlite3_reset并不改變在準備語句上的任何綁定值,那么這里猜測,可能是語句在被執(zhí)行的過程中發(fā)生了其他的改變,然后這個語句將它重置到綁定值的時候的那個狀態(tài)。
?
4.? sqlite3_column()
這個過程從執(zhí)行sqlite3_step()執(zhí)行一個準備語句得到的結(jié)果集的當前行中返回一個列。每次sqlite3_step得到一個結(jié)果集的列停下后,這個過程就可以被多次調(diào)用去查詢這個行的各列的值。對列操作是有多個函數(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);
說明
第一個參數(shù)為從sqlite3_prepare返回來的prepared statement對象的指針,第二參數(shù)指定這一行中的想要被返回的列的索引。最左邊的一列的索引號是0,行的列數(shù)可以使用sqlite3_colum_count()獲得。
這些過程會根據(jù)情況去轉(zhuǎn)換數(shù)值的類型,sqlite內(nèi)部使用sqlite3_snprintf()去自動進行這個轉(zhuǎn)換,下面是關(guān)于轉(zhuǎn)換的細節(jié)表:
| 內(nèi)部類型 | 請求的類型 | 轉(zhuǎn)換 |
| NULL | INTEGER | 結(jié)果是0 |
| NULL | FLOAT | 結(jié)果是0.0 |
| NULL | TEXT | 結(jié)果是NULL |
| NULL | BLOB | 結(jié)果是NULL |
| INTEGER | FLOAT | 從整形轉(zhuǎn)換到浮點型 |
| INTEGER | TEXT | 整形的ASCII碼顯示 |
| INTEGER | BLOB | 同上 |
| FLOAT | INTEGER | 浮點型轉(zhuǎn)換到整形 |
| FLOAT | TEXT | 浮點型的ASCII顯示 |
| FLOAT | BLOB | 同上 |
| TEXT | INTEGER | 使用atoi() |
| TEXT | FLOAT | 使用atof() |
| TEXT | BLOB | 沒有轉(zhuǎn)換 |
| BLOB | INTEGER | 先到TEXT,然后使用atoi |
| BLOB | FLOAT | 先到TEXT,然后使用atof |
| BLOB | TEXT | 如果需要的話添加0終止符 |
?
注:BLOB數(shù)據(jù)類型是指二進制的數(shù)據(jù)塊,比如要在數(shù)據(jù)庫中存放一張圖片,這張圖片就會以二進制形式存放,在sqlite中對應(yīng)的數(shù)據(jù)類型就是BLOB
?
int sqlite3_column_bytes(sqlite3_stmt*, int iCol)int sqlite3_column_bytes16(sqlite3_stmt*, int iCol)兩個函數(shù)返回對應(yīng)列的內(nèi)容的字節(jié)數(shù),這個字節(jié)數(shù)不包括后面類型轉(zhuǎn)換過程中加上的0終止符。
下面是幾個最安全和最簡單的使用策略
- 先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);
這個過程銷毀前面被sqlite3_prepare創(chuàng)建的準備語句,每個準備語句都必須使用這個函數(shù)去銷毀以防止內(nèi)存泄露。
在空指針上調(diào)用這個函數(shù)沒有什么影響,同時可以準備語句的生命周期的任一時刻調(diào)用這個函數(shù):在語句被執(zhí)行前,一次或多次調(diào)用sqlite_reset之后,或者在sqlite3_step任何調(diào)用之后不管語句是否完成執(zhí)行
?
6.? sqlite3_close
這個過程關(guān)閉前面使用sqlite3_open打開的數(shù)據(jù)庫連接,任何與這個連接相關(guān)的準備語句必須在調(diào)用這個關(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語句用的是sqlite3_exec,它是前面幾個函數(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語句而不要寫許多重復(fù)的代碼。
Sqlite3_exec接口執(zhí)行0或多個UTF-8編碼的,分號分割的sql語 句,傳到第二個參數(shù)中。如果sqlite3_exec的第三個參數(shù)回調(diào)函數(shù)指針不為空,那么它會為每個來自執(zhí)行的SQL語句的結(jié)果行調(diào)用(也就是說回調(diào)函 數(shù)會調(diào)用多次,上面例子中會返回2個結(jié)果行,因而會被執(zhí)行2次),第4個參數(shù)是傳給回調(diào)函數(shù)的第一個參數(shù),如果回調(diào)函數(shù)指針為空,那么回調(diào)不會發(fā)生同時結(jié) 果行被忽略。
如果在執(zhí)行sql語句中有錯誤發(fā)生,那么當前的語句的執(zhí)行被停止,后續(xù)的語句也被跳過。第五個參數(shù)不為空的時候,它被分配內(nèi)存并寫入了錯誤信息,所以在sqlite3_exec后面需要調(diào)用sqlite3_free去釋放這個對象以防止內(nèi)存泄露
?
轉(zhuǎn)載于:https://www.cnblogs.com/zhoug2020/p/4061071.html
總結(jié)
以上是生活随笔為你收集整理的sqlite3使用简介(内含解决sqlite内存的方法)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Discuz初探
- 下一篇: 用python写网络爬虫-英文翻译