Sqlite3 stmt 機制操作
參考文獻:https://blog.csdn.net/u012351051/category_8966045.html
sqlite 提供了SQL語句執行的函數sqlite3_exec,本文介紹的是sqlite3_stmt方式對數據庫進行操作。
官方文檔以及參考資料中給出的結論:如果只是單條命令,那么 使用sqlite3_exec和sqlite3_stmt效率是一樣的,但是在涉及到批量操作時,推薦使用sqlite3_stmt機制。在嵌入式軟件的開發中執行效率是一個關鍵因素,因此更加推薦使用stmt方式對數據庫進行操作。同時,stmt方式提供了更加細分的步驟,因此操作也更加靈活,在實際的開發過程中數據的方式也會更加多樣,更加便利。
- 操作步驟:
- 數據庫打開
sqlite3 * db_stmt_open(char *dbName)
{
sqlite3 *db = NULL;
int ret =0;
ret = sqlite3_open_v2(dbName,&db,SQLITE_OPEN_READWRITE | SQLITE_OPEN_FULLMUTEX ,NULL);
if(ret !=SQLITE_OK)
{
printf("db_stmt_open error!\n");
return NULL;
}
printf("db_stmt_open successful!\n");
return db;
}
- 指令準備
slqite3_prepare可以實現對sql語句(模板)的解析和編譯,生成了可以被執行的 sql語句實例。
SQLITE_API 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 */
);
int db_stmt_prepare(sqlite3 *db,const char *sql,sqlite3_stmt **stmt)
{
int ret;
ret=sqlite3_prepare_v2(db,sql,strlen(sql),stmt,NULL);
return ret;
}
- 變量綁定
該函數可以將變量綁定到sqlite3_prepare實力話的語句中。這個函數是非常方便的一個函數,在程序的設計過程中我們不能為每一個sql語句寫一個獨立的函數,通常是為同類的操作封裝操作接口。在sqlite的select insert等操作中可以為每個表單封裝通用接口,使用sqlite3_bind函數綁定傳入的參數即可。sqlite提供了多個bind函數原型。
// 綁定二進制變量
SQLITE_API int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
// 綁定double類型變量
SQLITE_API int sqlite3_bind_double(sqlite3_stmt*, int, double);
// 綁定int類型變量
SQLITE_API int sqlite3_bind_int(sqlite3_stmt*, int, int);
// 綁定text類型(char字符串)變量
SQLITE_API int sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*));
參數:
第一個參數:sqlite3_stmt: 準備語句變量指針。
第二個形參: sqlite3_stmt變量參數的序號索引值,規定最左側的SQL參數的索引值為 1,也就是說參數索引值從1開始。
第三個形參: 是要綁定給第2個形參指向的 變量參數的 實際值。第2個形參可以指向不同的索引值。
第四個形參: 對于有4個形參的函數,第4個形參一般是第3個形參的長度。
第五個形參: 是用于BLOB和字符串綁定后的 析構函數,用于在sqlite處理完blob或字符串之后處理它,一般可以設置為NULL。
關于綁定的位置關系,舉一個例子說明:
const char *sql = "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) " \
"VALUES (?, ?, ?, ?, ?); ";
ret = db_stmt_prepare(db,sql,&stmt);
if(ret == SQLITE_OK)
{
sqlite3_bind_int(stmt,1,id); // 對應第一個? 也就是id的值,是int 類型
sqlite3_bind_text(stmt,2,name,-1,SQLITE_STATIC); //對應第二個? 是name的值 text類型
sqlite3_bind_int(stmt,3,age);
sqlite3_bind_text(stmt,4,address,-1,SQLITE_STATIC);
sqlite3_bind_int(stmt,5,salary);
}
- SQL語句執行
sqlite3_step 函數用于執行sqlite3_prepare實例化的SQL語句,相當于sqlite3_exec的作用。
SQLITE_API int sqlite3_step(sqlite3_stmt*);
sqlite3_step函數的參數是被實例化的sql語句,重點需要關注其返回值。
#define SQLITE_ROW 100 /* sqlite3_step() has another row ready */
#define SQLITE_DONE 101 /* sqlite3_step() has finished executing */
比較常用的返回值就上面這兩個,下面做一下說明:
SQLITE_DONE::意味著sql語句執行完成,并且成功。
SQLITE_ROW:表示當前的返回結果中包含一行的結果數據。
執行select操作時若有數據返回時返回值時SQLITE_ROW,若無返回值時為SQLITE_DONE,有個別操作返回值是NULL時,sqlite3_step操作的返回值也會是SQLITE_ROW,例如:SELECT min(DataTime) FROM MYTABLE; 其中min是聚合函數,即使表為空仍要返回,因此函數中還需使用sqlite3_column_bytes()進行判斷,若返回0,則表示為NULL。
int db_stmt_exec(sqlite3_stmt *stmt)
{
int ret;
do{
ret=sqlite3_step(stmt);
if(ret==SQLITE_BUSY)
{
usleep(1000);
continue;
}
break;
}while(ret==SQLITE_BUSY);
return ret;
}
- SELECT 結果獲取
在sqlite3_exec方法獲取select結果時通常在callback函數中處理,在sqlite_stmt機制的處理中提供了sqlite3_count方法處理select的結果,根據數據類型的不同需要使用不同的方法,常用到的函數原型如下:
// 返回查找到的字節數
SQLITE_API int sqlite3_column_bype(sqlite3_stmt*, int iCol);
// 獲取二進制數據,配合sqlite3_column_type使用
SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);
// 獲取double類型數據
SQLITE_API double sqlite3_column_double(sqlite3_stmt*, int iCol);
// 獲取int類型的數據
SQLITE_API int sqlite3_column_int(sqlite3_stmt*, int iCol);
// 獲取char* 類型數據
SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);
第一個參數是被stmt實例化的sql語句,第二個指的是select結果的第幾個參數,編號從0開始,同時需要注意的是在sqlite3_colum_blob函數或者二進制結果時需要提前使用sqlite3_column_bype提前獲取字節數用于后期拷貝,防止數據越界。舉例說明一下:
if(SQLITE_ROW == sqlite3_step(stmt))
{
ret = sqlite3_column_bytes(stmt,0);
printf("select len: %d \n",ret);
if(ret>0 && ret <100){
memcpy(dataBuf,sqlite3_column_blob(stmt,0),ret);
printf("select result: %s \n",dataBuf);
}else
{ printf("select error!\n");
}
}
智能推薦
【python3】 sqlite3操作SQLite數據庫存取圖片
【python3】 sqlite3操作SQLite數據庫存取圖片 1.背景 2.code 3.運行結果 1.背景 SQLite 原生支持如下的類型: NULL,INTEGER,REAL,TEXT,BLOB。 因此可以將以下Python類型發送到SQLite而不會出現任何問題: 這是SQLite類型默認轉換為Python類型的方式: sqlite3 模塊的類型系統可通過兩種方式來擴展(本博文不涉及)...
freemarker + ItextRender 根據模板生成PDF文件
1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...
電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!
Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...
requests實現全自動PPT模板
http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...
猜你喜歡
Linux C系統編程-線程互斥鎖(四)
互斥鎖 互斥鎖也是屬于線程之間處理同步互斥方式,有上鎖/解鎖兩種狀態。 互斥鎖函數接口 1)初始化互斥鎖 pthread_mutex_init() man 3 pthread_mutex_init (找不到的情況下首先 sudo apt-get install glibc-doc sudo apt-get install manpages-posix-dev) 動態初始化 int pthread_...
統計學習方法 - 樸素貝葉斯
引入問題:一機器在良好狀態生產合格產品幾率是 90%,在故障狀態生產合格產品幾率是 30%,機器良好的概率是 75%。若一日第一件產品是合格品,那么此日機器良好的概率是多少。 貝葉斯模型 生成模型與判別模型 判別模型,即要判斷這個東西到底是哪一類,也就是要求y,那就用給定的x去預測。 生成模型,是要生成一個模型,那就是誰根據什么生成了模型,誰就是類別y,根據的內容就是x 以上述例子,判斷一個生產出...
styled-components —— React 中的 CSS 最佳實踐
https://zhuanlan.zhihu.com/p/29344146 Styled-components 是目前 React 樣式方案中最受關注的一種,它既具備了 css-in-js 的模塊化與參數化優點,又完全使用CSS的書寫習慣,不會引起額外的學習成本。本文是 styled-components 作者之一 Max Stoiber 所寫,首先總結了前端組件化樣式中的最佳實踐原則,然后在此基...