参数绑定:
和大多数关系型数据库一样,SQLite的SQL文本也支持变量绑定,以便减少SQL语句被动态
解析的次数,从而提高数据查询和数据操作的效率。要完成该操作,我们需要使用SQLite提
供的另外两个接口APIs,sqlite3_reset和sqlite3_bind。
见如下示例:
void test_parameter_binding() {
//1. 不带参数绑定的情况下插入多条数据。
char strSQL[128];
for (int i = 0; i < MAX_ROWS; ++i) {
sprintf(strSQL,"insert into testtable values(%d)",i);
sqlite3_prepare_v2(..., strSQL);
sqlite3_step(prepared_stmt);
sqlite3_finalize(prepared_stmt);
}
//2. 参数绑定的情况下插入多条数据。
string strSQLWithParameter = "insert into testtable values(?)";
sqlite3_prepare_v2(..., strSQL);
for (int i = 0; i < MAX_ROWS; ++i) {
sqlite3_bind(...,i);
sqlite3_step(prepared_stmt);
sqlite3_reset(prepared_stmt);
}
sqlite3_finalize(prepared_stmt);
}
这里首先需要说明的是,SQL语句"insert into testtable values(?)"中的问号(?)表示参数变量的
占位符,该规则在很多关系型数据库中都是一致的,因此这对于数据库移植操作还是比较方便
的。
通过上面的示例代码可以显而易见的看出,参数绑定写法的执行效率要高于每次生成不同的
SQL语句的写法,即2)在效率上要明显优于1),下面是针对这两种写法的具体比较:
1. 单单从程序表面来看,前者在for循环中执行了更多的任务,比如字符串的填充、SQL语句
的prepare,以及prepared_statement对象的释放。
2. 在SQLite的官方文档中明确的指出,sqlite3_prepare_v2的执行效率往往要低于
sqlite3_step的效率。
3. 当插入的数据量较大时,后者带来的效率提升还是相当可观的。
sqlite3_bind
和sqlite3_column一样,他也是一系列的函数,我们必须选择的用,它是用来给sqlite3_stmt *pStmt语句增加值的,对于不同类型的参数要选用不同的函数。
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); 具体的每个用法查询http://www.sqlite.org/c3ref/bind_blob.html 下面的列子中包含了他的用法 /插入数据 sqlite3_prepare(db, "INSERT INTO players (name,num) VALUES(?,?);", -1,&stmt,&zTail); char str[] = "Kevin"; int n = 23; sqlite3_bind_text(stmt,1,str,-1,SQLITE_STATIC); //绑定数据 sqlite3_bind_int(stmt,2,n); r = sqlite3_step(stmt); if( r!=SQLITE_DONE){ printf("%s",sqlite3_errmsg(db)); } sqlite3_reset(stmt); //重新复位下stmt语句 //插入第二个数据 char str2[] = "Jack"; int n2 = 16; sqlite3_bind_text(stmt,1,str2,-1,SQLITE_STATIC); sqlite3_bind_int(stmt,2,n2); r = sqltie3_step(stmt); if( r!=SQLITE_DONE){ printf("%s",sqlite3_errmsg(db)); } sqltie3_finalize(stmt);
例程:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sqlite3.h>
static sqlite3 *db;
int callback(void *NotUsed, int argc, char **argv, char **azColName){
int i;
for(i=0; i<argc; i++){
printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
}
printf("\n");
return 0;
}
sqlite3 *db_connect(char *db_name)
{
int rc;
rc = sqlite3_open(db_name, &db);
return db;
}
int db_exec_stmt(char *sql)
{
int rc;
char *zErrMsg = 0;
rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg);
if( rc!=SQLITE_OK ){
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
exit(1);
}
return 0;
}
void db_exec()
{
char *sql = "insert into user_info (id, user_name) values(?,?)";
sqlite3_stmt *stmt;
const char *tail;
int i;
int ncols;
int rc;
char *name="xiaoliang";
rc = sqlite3_prepare(db, sql, strlen(sql), &stmt, NULL);
if (rc != SQLITE_OK)
{
fprintf(stderr, "sql error:%s\n", sqlite3_errmsg(db));
}
sqlite3_bind_int(stmt, 1, 20);
sqlite3_bind_text(stmt, 2, name, strlen(name), SQLITE_STATIC);
sqlite3_step(stmt);
sqlite3_finalize(stmt);
}
int main(int argc, char **argv)
{
char *db_name="test.db";
db = db_connect(db_name);
// rc = db_exec_stmt(sql);
db_exec();
sqlite3_close(db);
return 0;
}