1. 程式人生 > >SQLite C-API帶引數的查詢/更新/刪除操作

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那樣的刪除,插入之類的命令。很多初學者就很納悶,那我怎麼刪除和插入呢?彆著急,我們先來尋找解決辦法。

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 */
);
上面是我在官方網站找到的sqlite3_prepare家族所有的C函式申明,我比較常用的是sqlite3_prepare_v2,查詢的過程可以是insert,update或者delete。這取決於sql字串的定義是怎麼樣子的,你想怎麼使用它而已。具體欄位含義,只講一個,sqlite3_stmt **ppStmt。一旦查詢語句就緒,下一步就是使用sqlite3_step()執行。SQLITE_BUSY也是在這裡被返回的。sqlite3_stmt 這個結構體,將位元組程式碼(我們通常所說的需要繫結的資料)關聯(繫結)到單個語句控制代碼。這種結構體比用來執行SQL語句並獲取相關記錄的不透明控制代碼的內容更多。但是,這種資料結構包含了命令的位元組碼,繫結的引數,B-tree遊標,執行上下文以及sqlite3_step()在執行過程中管理查詢狀態所需的其他資料。

我們可以使用如下任何一種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~~~~