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

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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章