C++ sqlite3使用指南

2021-03-02 數據結構與算法

wget http://www.sqlite.org/2017/sqlite-autoconf-3160200.tar.gz
tar xvzf sqlite-autoconf-3160200.tar.gz

./configure --host=arm-himix200-linux --prefix=/home/zjucad/wangzhiqiang/toolDir/sqlite-autoconf-3160200/libs
make
make install

按順序執行上述命令後sqlite的連結庫和頭文件等就會出現在prefix目錄下

基本的使用流程

sqlite3_open()->sqlite3_prepare_v2()->sqlite3_step()->sqlite3_column()->sqlite3_finalize()->sqlite3_close()

具體介紹:

int sqlite3_open(
 const char *filename,   /* Database filename (UTF-8) */
 sqlite3 **ppDb          /* OUT: SQLite db handle */
);
打開一個資料庫,第一個參數為資料庫的路徑,注意這裡不能為:memory:,這表示存在內存中,第二個參數為返回,返回這個資料庫的handle,函數返回值是int,成功則返回SQLITE_OK,失敗的話可以通過sqlite3_errmsg()查看錯誤信息。
註:sqlite還有個sqlite3_open_v2()函數,添加一些flag,看著不太常用。

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 */
);
準備資料庫語句的上下文,相當於編譯sql語句,最後由step函數執行編譯好的語句,ppStmt需要自己首先定義好,最後一個參數基本傳NULL。
註:sqlite還有個sqlite3_prepare()函數,但是現在官方推薦使用v2版本,有錯誤v2版本能夠立即暴露出來。

一般使用sqlite3_prepare_v2()都是和sqlite3_bind_xxx()系列函數一起使用,例如執行插入語句,使用sqlite3_bind_xxx()可以動態綁定某些參數的值,後續給出示例代碼。

int sqlite3_step(sqlite3_stmt*);
執行資料庫語句

int sqlite3_reset(sqlite3_stmt *pStmt);
重置資料庫上下文,當需要重新bind參數時可以使用這個函數,避免多次prepare。

int sqlite3_finalize(sqlite3_stmt *pStmt);
刪除資料庫語句的上下文,調用了sqlite3_prepare_v2()後無論成功失敗都需要調用,避免內存洩漏。

int sqlite3_close(sqlite3 *);
關閉資料庫

在執行查詢操作時,可能結果不止一條,那sqlite3_step()函數就會返回SQLITE_ROW直到所有結果都被查詢到會返回SQLITE_DONE,這裡每次sqlite3_step()返回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);
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);

執行查詢語句後需要使用這類函數,獲取查詢到的結果,第二個參數代表第幾列,需要根據資料庫表的每一列具體類型調用相應的函數,可以通過sqlite3_column_type()獲取某一列的類型,通過sqlite3_column_count()函數獲取這次查詢結果共有多少列。

在一些簡單的場景下也可以使用sqlite3的wrapper函數
主要有sqlite3_exec()和sqlite3_get_table()函數,相當於調用了sqlite3_prepare_v2()->sqlite3_step()->sqlite3_finalize()這個流程。

區別是sqlite3_exec()在查詢中需要添加回調函數,sqlite3_get_table()主要用在查詢上,沒有回調,會把查詢到的結果存到一塊地址。

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 */
);

注意這裡的最後一個參數是錯誤信息,如果執行函數沒有返回SQLITE_OK,可以查看errmsg處的信息,這塊內存也需要自己手動調用sqlite3_free()來釋放。

int sqlite3_get_table(
 sqlite3 *db,          /* An open database */
 const char *zSql,     /* SQL to be evaluated */
 char ***pazResult,    /* Results of the query */
 int *pnRow,           /* Number of result rows written here */
 int *pnColumn,        /* Number of result columns written here */
 char **pzErrmsg       /* Error msg written here */
);
void sqlite3_free_table(char **result);

sqlite3_get_table()主要用在查詢上,會把查詢到的結果存到一塊地址。由調用者手動調用sqlite3_free_table()釋放內存。

sqlite3-column-text()等函數返回的地址不需要自己free,sqlite會在調用sqlite3_step() or sqlite3_reset() or sqlite3_finalize()時自動釋放

如何設置自增欄位
欄位是integer 的primary key就會自增

CREATE TABLE t1(
a INTEGER PRIMARY KEY,
b INTEGER
);

如上代碼,欄位a就會自增,最大值是9223372036854775807,如果insert超過了這個數量,就會返回SQLITE_FULL錯誤,但90%的資料庫行數可能不會超過這個數量。

sqlite3 *db_;
std::string sql =
       "create table if not exists sqlite("
       "id INTEGER primary key     AUTOINCREMENT,"
       "value      int64      not null);";
char *err_msg = NULL;
int ret = sqlite3_exec(db_, sql.c_str(), NULL, 0, &err_msg);
if (ret != SQLITE_OK) {
   std::cout << "create table error " << err_msg;
   sqlite3_free(err_msg);
   return false;
}

std::string sql =
       "insert into sqlite(value) values(?1)";
sqlite3_stmt *stmt;
int ret = sqlite3_prepare_v2(db_, sql.c_str(), -1, &stmt, NULL);
if (ret != SQLITE_OK) {
   std::cout << "prepare sql error " << ret << " " << sqlite3_errcode(db_);
   return false;
}
if (sqlite3_bind_int64(stmt, 1, 1) != SQLITE_OK) {
   std::cout << "bind timestamp error " << sqlite3_errcode(db_);
   return false;
}
if (sqlite3_step(stmt) != SQLITE_DONE) {
   std::cout << "step insert fail " << sqlite3_errcode(db_);
   return false;
}
sqlite3_finalize(stmt);

相關焦點

  • 月考+通過Python使用Sqlite3的7個技巧
    預計閱讀時間:8分鐘我最近在做一個項目,這個項目大量地使用sqlite3來進行數據存儲和處理。
  • Google C++項目編程風格指南 (中文版) 分享
    源GitHub項目:https://github.com/google/styleguide中文翻譯:https://github.com/zh-google-styleguide/zh-google-styleguide如果下載有問題,可以在後臺回覆:「c++
  • 嵌入式 | sqlite3的使用
    簡介sqlite3是一個開源的、內嵌式的、輕量級的關係型資料庫,廣泛應用於嵌入式物聯網領域。
  • json for modern c++的使用
    json for modern c++是一款非常好用的json庫,具有語法直觀和使用簡單的特點,並且是用C++11標準編寫的,此外還支持STL和json容器之間的轉換,可謂集方便又強大。本文推薦給廣大C++程式設計師,相信學習完本文之後,在處理json時一定會得心應手。
  • Python內置庫SQlite3使用指南
    如果你是軟體開發人員,相信你一定知道或者曾經使用過一個非常輕量級的資料庫—
  • C++機器學習庫介紹
    目錄為什麼我們要使用機器學習庫?C++中的機器學習庫SHARK 圖書館MLPACK庫為什麼我們要使用機器學習庫?這是很多新來者都會遇到的問題。庫在機器學習中的重要性是什麼?讓我試著在這一節解釋一下。這有一份安裝指南:http://www.shark-ml.org/sphinx_pages/build/html/rest_sources/tutorials/tutorials.html使用Shark編譯程序包括相關的頭文件。
  • c++的輸入與輸出
    c++輸入與輸出C++ 標準庫提供了一組豐富的輸入/輸出功能,本章將討論 C++ 編程中最基本和最常見的 I/O 操作。輸入輸出並不是c++語言的正式組成成分,c和c++沒有為輸入輸出提供專門的結構。在c語言中輸入輸出是通過調用scanf和printf 實現的,在c++中是通過調用流對象cin和cout實現的。
  • C++、java 和 C 的區別
    一、基礎類型c++:** java:** C#:1.以java為準,c++裡面的int short long 像這樣的整型 一般都有unsigned 和signed的區分 ,這個跟java和c# 的區別比較大,但c#裡面有unit ulong ushort 這三種就相當於c++的修飾詞unsigned,當c++李明的變量類型定義unsigned,就默認是整數。
  • 使用SWIG封裝C++為python庫
    之前給C++程序做單元測試,有過兩種方式:一是自己寫專門的測試demo,二是使用gtest框架。
  • C++機器學習庫介紹 | 文末送書
    目錄為什麼我們要使用機器學習庫?這是很多新來者都會遇到的問題,庫對於機器學習中的重要性是什麼?讓我試著在這一節解釋一下。比如說,經驗豐富的專業人士和行業老手已經付出了艱辛的努力,並想出了解決問題的辦法。你更願意使用它,還是願意花幾個小時從頭開始重新創建相同的東西?後一種方法通常沒有什麼意義,尤其是當你在DDL前的工作或學習。
  • 學習c++筆記——標準輸出流cout
    前和往常一樣,一邊喝早茶,一邊上網和女粉絲侃大山,在手機和平板電腦上整理修改《html5》、《javascript》、《css3》、《c語言》等多年前寫的教程(c++
  • 那些容易犯錯的c++保留字
    本文首發 | 公眾號:lunvey目前正在學習vc++6.0開發,而這裡面使用的是c++98標準。
  • C++ 優先隊列priority_queue
    這三個參數的含義分別為:數據類型,容器類型和比較函數,實際上優先隊列就是維護了一個裝有 T 類型元素的容器 Container,並在入隊和出隊時對容器內元素使用 Compare 比較函數進行了排序。這3個參數還要滿足一定的要求,並且在使用過程中有些注意事項:1.
  • 九大程式語言優缺點第四期:c++
    C++:c++誕生於1983年,緊隨c語言的步伐,c++是C語言的超集,大家所知道的C語言是面向過程的,java是面向對象的,那麼C語言為了面向對象,所以誕生出現在大家所熟知的c++,被廣泛視為大規模應用構建軟體。
  • 混合使用C、C++和彙編語之:內聯彙編和嵌入型彙編的使用
    使用它可以在C/C++程序中實現C/C++語言不能完成的一些工作。例如,在下面幾種情況中必須使用內聯彙編或嵌入型彙編。·程序中使用飽和算術運算(Saturatingarithmetic),如SSAT16和USAT16指令。·程序中需要對協處理器進行操作。
  • python+C、C++混合編程的應用
    有的語言專注於簡單高效,比如python,內建的list,dict結構比c/c++易用太多,但同樣為了安全、易用,語言也犧牲了部分性能。在有些領域,比如通信,性能很關鍵,但並不意味這個領域的coder只能苦苦掙扎於c/c++的陷阱中,比如可以使用多種語言混合編程。
  • c++11新特性,所有知識點都在這了!
    c++11新特性吧,你是怎麼回答的呢?的模板改進並發c++11關於並發引入了好多好東西,有:詳細介紹請看:c++11新特性之線程相關所有知識點這裡也使用c++11來實現的線程池和定時器,可以看:,然而這種問題其實都可以通過c++11引入的智能指針來解決,相反我還認為這種內存管理還是c++語言的優勢,因為盡在掌握。
  • 跟我學C++中級篇——STL的學習
    一、c++標準庫C++的標準庫主要包含兩大類,首先是包含C的標準庫的,當然,為了適應c++對一些C庫進行了少許的修改和增加。最重要的當然是面向對象的c++庫;而c++庫又可以分成兩大類,即面向對象的c++庫和標準模板庫,也就是題目中的STL。
  • C++伺服器開發完整學習路線(含免費學習資料下載地址)
    surl=eQAdygU  密碼:6mhv學了c++基礎後,為了寫出更高效的c++代碼,那麼就須要看這本書《Effective C++》  連結:https://pan.baidu.com/s/1eewVI  2. linux基礎linux系統安裝和命令、工具使用  c++伺服器程序基本都是運行在linux系統下面,所以對於linux的系統安裝
  • python3使用ctypes在windows中訪問C和C++動態連結庫函數示例
    python3使用ctypes在windows中訪問C和C++動態連結庫函數示例這是我們的第一個示例,我們儘量簡單,不傳參,不返回,不訪問其他的動態連結庫一 測試環境介紹和準備Python3.7.0 (源碼和安裝文件)http://ffmpeg.club/python二 C/C++部分代碼1 首先完成C/C++的動態連結庫,與做python擴展庫不同,ctypes調用的c++