一、C/C++ 接口 API
主要通过通过sqlite3_open,sqlite3_exec和qlite3_close来实现一个简单的数据库操作。
1.1、sqlite3_open
sqlite3_open(const char *filename, sqlite3 **ppDb)
- 打开一个指向 SQLite 数据库文件的连接,返回一个用于其他 SQLite 程序的数据库连接对象
filename
参数是NULL
或':memory:'
,sqlite3_open()
将会在 RAM 中创建一个内存数据库,这只会在 session 的有效时间内持续filename
不为NULL
,sqlite3_open()
将使用这个参数值尝试打开数据库文件。如果该名称的文件不存在,sqlite3_open()
将创建一个新的命名为该名称的数据库文件并打开
1.2、sqlite3_exec
sqlite3_exec(sqlite3*, const char *sql, sqlite_callback, void *data, char **errmsg)
- 提供了一个执行 SQL 命令的快捷方式,SQL 命令由
sql
参数提供,可以由多个 SQL 命令组成 - 第一个参数
sqlite3
是打开的数据库对象,sqlite_callback
是一个回调data
作为其第一个参数errmsg
将被返回用来获取程序生成的任何错误 sqlite3_exec()
程序解析并执行由sql
参数所给的每个命令,直到字符串结束或者遇到错误为止
1.3、sqlite3_close
sqlite3_close(sqlite3*)
- 关闭之前调用
sqlite3_open()
打开的数据库连接。所有与连接相关的语句都应在连接关闭之前完成。如果还有查询没有完成,sqlite3_close()
将返回SQLITE_BUSY
禁止关闭的错误消息
1.4、插入例程
void jobSerialInsertSQL(struct S_SERIAL_JOB serialjob)
{
char* insertJob;
char sql[255];
sqlite3 *db;
int rc;
char *zErrMsg = 0;
rc = sqlite3_open("jp.db",&db);
if(rc)
{
printf("Can not open database:%s\n",sqlite3_errmsg(db));
return;
}
insertJob = "INSERT INTO rt_jobserial (task_serial,task_id,point_tag,device_tag) VALUES (";
sprintf(sql,"%s%d%s%d%s%d%s%d%s",
insertJob,
serialjob.task_serial,
",",
serialjob.task_id,
",",
serialjob.point_tag,
",",
serialjob.device_tag,
")");
rc = sqlite3_exec(db,sql,sqliteCallback,0,&zErrMsg);
if( rc != SQLITE_OK)
{
printf("SQL ERROR: %s\n",zErrMsg);
sqlite3_free(zErrMsg);
}
else{}
sqlite3_close(db);
}
经过测试,上面代码在for循环运行插入1500条数据大约耗时1~2分钟,效率很低,在工程中是无法满足需求的。
默认SQLite的数据库插入操作,如果没有采用事务的话,它每次写入提交,就会触发一次事务操作,而这样几千条的数据,就会触发几千个事务的操作,这就是时间耗费的根源。
二、事务实现
2.1、什么是事务?
事务是用户定义的一些列数据操作,这些操作是一个完整的不可分的工作单元。一个事务要么全部执行,要么全部不执行。
2.2、事务属性(ACID)
原子性(Atomicity): 确保工作单位内的所有操作都成功完成,否则,事务会在出现故障时终止,之前的操作也会回滚到以前的状态。
一致性(Consistency):确保数据库在成功提交的事务上正确地改变状态。
隔离性(solation): 使事务操作相互独立和透明。
持久性(Durability): 确保已提交事务的结果或效果在系统发生故障的情况下仍然存在。
2.3、事务控制
事务控制命令只与 DML 命令 INSERT
、UPDATE
和DELETE
一起使用。他们不能在创建表或删除表时使用,因为这些操作在数据库中是自动提交的。
BEGIN TRANSACTION
:开始事务处理。COMMIT
:保存更改,或者可以使用 END TRANSACTION 命令。ROLLBACK
:回滚所做的更改。
2.4、事务例程
void jobSerialInsertSQL(struct S_SERIAL_JOB *serialjob,int totalNum)
{
char* insertJob;
char sql[255];
sqlite3 *db;
int rc;
char *zErrMsg = 0;
int i = 0;
bool isExecSuccess = true;
rc = sqlite3_open("jp.db",&db);
if(rc)
{
printf("Can not open database:%s\n",sqlite3_errmsg(db));
return;
}
sqlite3_exec(db, "begin;", 0, 0, &zErrMsg); //开启事务
insertJob = "INSERT INTO rt_jobserial (task_serial,task_id,point_tag,device_tag) VALUES (";
for(i=0;i<totalNum;i++)
{
sprintf(sql,"%s%d%s%d%s%d%s%d%s",
insertJob,
serialjob[i].task_serial,
",",
serialjob[i].task_id,
",",
serialjob[i].point_tag,
",",
serialjob[i].device_tag,
")");
rc = sqlite3_exec(db,sql,sqliteCallback,0,&zErrMsg);
memset(sql,0,255);
if( rc != SQLITE_OK)
{
isExecSuccess = false;
printf("SQL ERROR: %s\n",zErrMsg);
sqlite3_free(zErrMsg);
}
else{}
}
if(isExecSuccess)
{
sqlite3_exec(db, "commit;", 0, 0, 0);
}
else
{
sqlite3_exec(db, "rollback;", 0, 0, 0);
}
sqlite3_close(db);
}
经过测试,上面代码插入1500条数据所需时间约为 70~90 ms。