在項目中遇到需要判斷sqlite數據庫中某個表是否存在,上網搜索一些資料后,解決了問題,如下:
首先,在每個sqlite數據庫中,都有一個名為sqlite_master的表,它定義了數據庫的模式,它的結構如下:
sqlite_master (
type TEXT, //項目的類型,如table、index、view、trigger
name TEXT, //項目的名稱,如表名、索引名等
tbl_name TEXT, //所從屬的表名,如索引所在的表名。對於表來說,該列就是表名本身
rootpage INTEGER, //項目在數據庫頁中存儲的編號。對於視圖和觸發器,該列值為0或者NULL
sql TEXT //創建該項目的SQL語句
);
這個表中記錄了數據庫中的相關信息,我們通過在這個表中查找我們需要判斷的表來判斷其是否存在。相關代碼如下:
char strFindTable[128];
sprintf_s(strFindTable, "SELECT * FROM where type ='table' and name ='%s'", tabletname); //tablename為表名
sqlite3_stmt* stmt0 = NULL;
if (sqlite3_prepare_v2(conn, strFindTable, strlen(strFindTable), &stmt0, NULL) != SQLITE_OK) {
if (stmt0)
sqlite3_finalize(stmt0);
sqlite3_close(conn);
cout << "語句初始化錯誤";
return;
}
int r = sqlite3_step(stmt0);
//判斷表存在,結果集是否已到末尾
//通過sqlite3_step命令執行創建表的語句。對於DDL和DML語句而言, sqlite3_step執行正確的返回值
//只有SQLITE_DONE,對於SELECT查詢而言,如果有數據返回SQLITE_ROW,當到達結果集末尾時則返回SQLITE_DONE。
if (r == SQLITE_DONE){
cout<<"table doesn't existed";
}
else if (r == SQLITE_ROW){
cout<<"table had existed";
}
這里要注意的是,當sqlite_master表中沒有我們查詢的表時,它返回的結果集並不會為空,它先返回表項,所以需要使用sqlite3_step。該函數用於評估sqlite3_prepare函數返回的prepared_statement對象,在執行完該函數之后,prepared_statement對象的內部指針將指向其返回的結果集的第一行。如果打算進一步迭代其后的數據行就需要不斷的調用該函數,直到所有的數據行都遍歷完畢。在這里,使用了sqlite3_step之后,如果返回的是SQLITE_DONE,就說明結果集到了末尾,也就是說沒有找到我們判斷存在與否的表,即表不存在;如果返回的是SQLITE_ROW,說明在sqlite_master中找到了表相關的信息,即表存在。