天天看點

SQLite3使用筆記(1)——查詢

詳細介紹了使用SQLite3進行資料庫查詢的操作。

目錄

  • 1. 概述
  • 2. 詳論
    • 2.1. 打開/關閉資料庫
    • 2.2. 資料查詢
  • 3. 參考

1. 概述

SQLite是一個嵌入式SQL資料庫引擎。與大多數其他 SQL 資料庫不同,SQLite 沒有單獨的伺服器程序。SQLite 直接讀寫普通磁盤檔案。具有多個表、索引、觸發器和視圖的完整SQL資料庫包含在單個磁盤檔案中。

SQLite比MySQL還要輕量級,官方提供的程式包大約1MB。但是這麼小的内容居然也是一個關系型資料庫,是以SQLite也很适合作為入門資料庫。其中,SQL最基礎的功能就是查詢了。

2. 詳論

2.1. 打開/關閉資料庫

使用資料庫的第一步當然是打開資料庫了。對于C接口來說,通常的實作是提供一個打開的接口,得到一個句柄或者指針,然後通過這個句柄或者指針進行進一步操作,包括關閉資料庫操作。SQLite正是這麼設計的:

int nRes = sqlite3_open("D:/test.db", &pDB);
  if (nRes != SQLITE_OK) {
    cout << "Open database fail: " << sqlite3_errmsg(pDB);
    return 1;
  }


  sqlite3_close(pDB);
           

通過sqlite3_open()這個函數打開資料庫檔案,如果資料庫.db檔案不存在,則會建立這個檔案檔案。一旦建立成功,在程式結束時最好調用sqlite3_close()這個函數進行關閉,否則會記憶體洩漏。如果需要更加精細的打開資料庫檔案控制,最好使用sqlite3_open_v2()這個接口:

int flags =
      SQLITE_OPEN_READWRITE | SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_SHAREDCACHE;
  int nRes = sqlite3_open_v2("D:/test.db", &pDB, flags, nullptr);
           

sqlite3_open_v2()提供了很多打開資料庫檔案時的配置,例如如果需要在資料庫檔案不存在時進行建立,可以再加上SQLITE_OPEN_CREATE。

2.2. 資料查詢

如果在可視化管理工具(例如SQLite Expert)中,無論是查詢、插入、修改或者删除操作,都是直接輸入SQL語句,然後執行運作操作,就可以得到相應的結果。SQLite也有這樣的接口sqlite3_exec(),例如我們查詢一個表中所有的資料:

char* cErrMsg;
  int res =
      sqlite3_exec(pDB, "select * from metadata;", ResultCallBack, 0, &cErrMsg);

  if (res != SQLITE_OK) {
    cout << "select fail: " << cErrMsg << endl;
    return false;
  }

  sqlite3_free(cErrMsg);
           

sqlite3_exec()是一個回調函數,每查詢到一行資料就調用一次:

int ResultCallBack(void* NotUsed, int argc, char** argv,
                          char** azColName) {
  for (int i = 0; i < argc; i++) {
    cout << azColName[i] << " = " << (argv[i] ? argv[i] : "NULL") << ", ";
  }
  cout << endl;

  return 0;
}
           

如果需要進行更加細粒度的控制,那麼一個合适的做法是使用statement(語句)。首先,我們将我們需要的sql語句編譯成資料庫引擎識别的位元組碼,這個步驟可以叫做prepare(準備):

sqlite3_stmt* statement = nullptr;
  int ret = sqlite3_prepare_v2(pDB, sqlStr, -1, &statement, nullptr);
  if (ret != SQLITE_OK) {
    printf("prepare error ret : %d\n", ret);
    return 1;
  }
           

接着,就是執行準備好的SQL語句:

while (sqlite3_step(statement) == SQLITE_ROW) {	  	   
      //...
  }
           

sqlite3_setp()每次查詢一行記錄,并且傳回SQLITE_ROW;知道查詢完成,就傳回SQLIET_DONE。通過這種方式實作了一種類似疊代器的操作,循環周遊每個查詢結果。

最後,我們對每一行查詢的結果進行解析:

while (sqlite3_step(statement) == SQLITE_ROW) {
    cout << sqlite3_data_count(statement) << '\n';
    cout << sqlite3_column_text(statement, 0) << '\t'
         << sqlite3_column_text(statement, 1) << '\n';
  }
           

sqlite3_column_X是一系列函數,可以直接擷取每一行相應列的資料類型。例如擷取整型就是sqlite3_column_int。

另外,不要忘了關閉這個語句:

sqlite3_finalize(statement);
           

3. 參考

  1. SQLite3中核心C API