SQLite C-API帶引數的查詢/更新/刪除操作
SQLite使用範圍很廣,這由其SQL語言可擴充套件性決定的。這其中就包括了C,Perl,Python,Ruby,Java和一些其他的主流程式設計語言。我們這裡只討論C語言內對SQLite的使用細節。
我在以前使用Java些Android的時候,Android使用java封裝了很多資料庫操作的函式介面,比如delete,insert,replace等等,都有專門的介面。其實這些函式介面後臺都被編譯成了一條條的SQL語句,你也可以直接使用sqlite3_exec(****)直接執行SQL語句。既然如此,何必使用呆板的介面語句?這等於浪費廣大程式設計師的時間去了解幾個多餘的封裝函式,簡直就是沒有必要的。直接使用SQL語句不更加方便明瞭?C也是如此,我們可以發現,C-API中並沒有像Android中封裝的那麼厲害。
C/C++介面介紹:http://www.sqlite.org/c3ref/intro.html
其中函式部分連結:http://www.sqlite.org/c3ref/funclist.html
在裡面你找不到像Android那樣的刪除,插入之類的命令。很多初學者就很納悶,那我怎麼刪除和插入呢?彆著急,我們先來尋找解決辦法。
上面是我在官方網站找到的sqlite3_prepare家族所有的C函式申明,我比較常用的是sqlite3_prepare_v2,查詢的過程可以是insert,update或者delete。這取決於sql字串的定義是怎麼樣子的,你想怎麼使用它而已。具體欄位含義,只講一個,sqlite3_stmt **ppStmt。一旦查詢語句就緒,下一步就是使用sqlite3_step()執行。SQLITE_BUSY也是在這裡被返回的。sqlite3_stmt 這個結構體,將位元組程式碼(我們通常所說的需要繫結的資料)關聯(繫結)到單個語句控制代碼。這種結構體比用來執行SQL語句並獲取相關記錄的不透明控制代碼的內容更多。但是,這種資料結構包含了命令的位元組碼,繫結的引數,B-tree遊標,執行上下文以及sqlite3_step()在執行過程中管理查詢狀態所需的其他資料。Compiling An SQL Statement int sqlite3_prepare( 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 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 sqlite3_prepare16( sqlite3 *db, /* Database handle */ const void *zSql, /* SQL statement, UTF-16 encoded */ int nByte, /* Maximum length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const void **pzTail /* OUT: Pointer to unused portion of zSql */ ); int sqlite3_prepare16_v2( sqlite3 *db, /* Database handle */ const void *zSql, /* SQL statement, UTF-16 encoded */ int nByte, /* Maximum length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const void **pzTail /* OUT: Pointer to unused portion of zSql */ );
我們可以使用如下任何一種C介面給其繫結資料:
Binding Values To Prepared Statements
int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
int sqlite3_bind_double(sqlite3_stmt*, int, double);
int sqlite3_bind_int(sqlite3_stmt*, int, int);
int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64);
int sqlite3_bind_null(sqlite3_stmt*, int);
int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*));
int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
具體都是繫結什麼,希望大家自己去看看。
接下來就是可以呼叫sqlite3_step()去執行你所需要執行的刪除,插入,更新,查詢操作了。這就是我們稱之為帶引數的C語言SQLite操作。
下面是幾個例子程式碼片段:
插入或替換
sql = "insert or replace into fpgaData(id, dev_num, state_flg, error_cd, present_p, power, year, month, day, min) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
if(sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) == SQLITE_OK){
//bind data for insert new line, total 1 line
sqlite3_bind_int(stmt, 1, 1);
......
sqlite3_step(stmt);
sqlite3_finalize(stmt);
}else{
sqlite3_finalize(stmt);
return 1;
}
查詢
sql= "select wh,year,month,day from totalPwy order by year,month,day ASC ";
if(sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) == SQLITE_OK){
*count = 0;
while(sqlite3_step(stmt) == SQLITE_ROW){
<span style="white-space:pre"> </span>(currentp->wh) = sqlite3_column_int(stmt, 0);
......
}
sqlite3_finalize(stmt);
}
else{
sqlite3_finalize(stmt);
}
刪除
sql = "delete from fpgaData where dev_num=?";
if(sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) == SQLITE_OK){
sqlite3_bind_int(stmt, 1, dev_num);
while(sqlite3_step(stmt) == SQLITE_ROW);
sqlite3_finalize(stmt);
}
else{
sqlite3_finalize(stmt);
return 1;
}
更新
sql = "update fpgaData set state_flg=?, error_cd=?, present_p=?, power=?, year=?, month=?, day=?, min=? \
where id=? and dev_num=?";
int data_p;
for(data_p = 1; data_p <= *dev_cnt; data_p++){
if(sqlite3_prepare_v2(
db, sql, -1, &stmt, NULL) == SQLITE_OK){
//bind data for updata new line, total 48 line
sqlite3_bind_int(stmt, 1, s_data[(data_p-1)*10 + 2]); //status flags
.....
....
sqlite3_step(stmt);
sqlite3_finalize(stmt);
}else{
sqlite3_finalize(stmt);
data_p--;
}
}
當然,也可以直接使用sqlite3_exec()執行sql語句。在實際應用中,你會發現每個查詢函式都有其用途。sqlite3_exec()對於修改資料庫的命令(建立,丟棄,插入,更新,刪除)特別合適,我的理解是不帶引數的操作,用它會加快速度,而且一點都不繁瑣。反之,則使用sqlite3_prepare()進行編譯,sqlite3_step()進行執行會比較好。最後,不要忘記使用sqlite3_finalize()釋放stmt結構體,關閉查詢,這個具體原因我沒有深究,請各位自己探討了,畢竟是寫給新手看的。諒解。。。。
sqlite3_exec()和sqlite3_step()(執行查詢)類似,但是提供的功能較少,可以自定義封裝的餘地小。而sqlite3_get_table()(獲取表查詢)返回的是單獨一個SQL命令中的整個結果集,他也可以連續執行多條SQL命令,具體希望讀者自行去SQLite官網查閱怎麼使用。
OVER~~~~