本文为笔者首次在CSDN上开博,博文风格需要探索,先共享一下开发C++工程时,使用SQlite3的关键性方法做福利贴,以期开门红。
sqlite3简介:(以下描述来自百度百科)
SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。它能够支持Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如 Tcl、C#、PHP、Java等,还有ODBC接口,同样比起Mysql、PostgreSQL这两款开源世界著名的数据库管理系统来讲,它的处理速度比他们都快。SQLite第一个Alpha版本诞生于2000年5月。 至今已经有14个年头,SQLite也迎来了一个版本 SQLite 3已经发布。
笔者看来,sqlite3类似于微软的Access,可以嵌入在应用程序中,以动态库方式调用,常用的方法就是3,4个,易学易用,同时支持sql98语法,常用的SQL语法可直接用,效率还是杠杠的。比起在INI,或者XML文件等方式存储数据方便多了。而且还是标准的数据库方式。 但是SQlite不支持远程数据库,定位就是小型的嵌入式数据库,选择时看看场景是否合适。
闲言少许,开始正题,直接粘贴处源码。(开发时使用的是C++ builder工具,一下代码中有几个地方为C++ builder的语法,有需要的可以可以自己修改一下)
String getDBPath()
{
String dbpath = ExtractFilePath(Application->ExeName)+ "deviceinfo.db";
//sqlite 默认使用UTF-8编码,中文路径名需要改为UTF-8。
return AnsiToUtf8(dbpath);
}
typedef int (*dbcallback)(void*,int,char**, char**);
//查询设备信息列表,以回调函数方式显示到界面上;
int selectAllDevices(dbcallback funcName, void *pUserdata)
{
//插入数据库
sqlite3 *db = NULL;
char *errmsg = NULL;
int result;
//打开数据库
result = sqlite3_open(getDBPath().c_str(), &db);
if(result != SQLITE_OK)
{
//write_log("db打开失败!!");
return -1;
}
String insertsql = "select EQId,EQName from EQINFO";
//执行插入
result = sqlite3_exec(db, insertsql.c_str(), funcName, pUserdata, &errmsg);
if(result != SQLITE_OK )
{
//write_log("插入记录失败,错误码:%d,错误原因:%s/n", result, errmsg);
return -1;
}
//关闭数据库
sqlite3_close(db);
return 0;
}
//插入设备信息
int InsertDevice(int eqid, char *eqName)
{
//插入数据库
sqlite3 *db = NULL;
char *errmsg = NULL;
int result;
//打开数据库
result = sqlite3_open(getDBPath().c_str(), &db);
if(result != SQLITE_OK)
{
//write_log("db打开失败!!");
return -1;
}
String insertsql = "insert into EQINFO(EQId, EQName) values (";
insertsql += IntToStr(eqid);
insertsql += ", '";
insertsql += eqName;
insertsql += "')";
//执行插入
result = sqlite3_exec(db, insertsql.c_str(), 0, 0, &errmsg);
if(result != SQLITE_OK )
{
//write_log("插入记录失败,错误码:%d,错误原因:%s/n", result, errmsg);
return -1;
}
//关闭数据库
sqlite3_close(db);
return 0;
}
//修改设备信息
int updateEQNameByEQId(int eqid , char *eqName)
{
//插入数据库
sqlite3 *db = NULL;
char *errmsg = NULL;
int result;
//打开数据库
result = sqlite3_open(getDBPath().c_str(), &db);
if(result != SQLITE_OK)
{
//write_log("db打开失败!!");
return -1;
}
;
String insertsql = "update EQINFO set EQName = '";
insertsql += eqName;
insertsql += "' where EQId = ";
insertsql += IntToStr(eqid);
//执行插入
result = sqlite3_exec(db, insertsql.c_str(), 0, 0, &errmsg);
if(result != SQLITE_OK )
{
//write_log("插入记录失败,错误码:%d,错误原因:%s/n", result, errmsg);
return -1;
}
//关闭数据库
sqlite3_close(db);
return 0;
}
//删除设备信息
int deleteDeviceByEQId(int eqid)
{
//插入数据库
sqlite3 *db = NULL;
char *errmsg = NULL;
int result;
//打开数据库
result = sqlite3_open(getDBPath().c_str(), &db);
if(result != SQLITE_OK)
{
//write_log("db打开失败!!");
return -1;
}
;
String insertsql = "delete from EQINFO where EQId = ";
insertsql += IntToStr(eqid);
//执行插入
result = sqlite3_exec(db, insertsql.c_str(), 0, 0, &errmsg);
if(result != SQLITE_OK )
{
//write_log("插入记录失败,错误码:%d,错误原因:%s/n", result, errmsg);
return -1;
}
//关闭数据库
sqlite3_close(db);
return 0;
}
//检索当前Id是否在存在
bool ifExitByEQId(int eqid)
{
bool beidexit = false;
//插入数据库
sqlite3 *db = NULL;
char *errmsg = NULL;
char **dbResult;
int result;
int nRow, nColumn;
//打开数据库
result = sqlite3_open(getDBPath().c_str(), &db);
if(result != SQLITE_OK)
{
//write_log("db打开失败!!");
return false;
}
String insertsql = "select count(*) from EQINFO where EQId = ";
insertsql += IntToStr(eqid);
result = sqlite3_get_table(db, insertsql.c_str(), &dbResult, &nRow, &nColumn, &errmsg);
if(SQLITE_OK == result && nRow == 1 && atoi(dbResult[nColumn]) > 0)
{
beidexit = true;
}
else
{
beidexit = false;
}
sqlite3_free_table( dbResult );
sqlite3_close(db);
return beidexit;
}
说明如下:
1.sqlite3使用sqlite3_open()方法中的DB文件路径,如果出现中文字符会打不开的,以为sqlite默认使用UTF-8编码,需要路径转换成UTF-8编码才行;(笔者一开始使用的是相对路径,不存在此问题,后来设计应用程序开机自启动时就出现DB文件打不开,最后确定是中文路径的问题)
2.sqlite3_exec()第三个参数为一个回调函数,一般Insert, update, delete操作时用不到,赋值NULL即可;只用在查询多条记录,多字段的情况用回调比较好,回调后逐条调用查询中的记录;(笔者的方法主要是将表中的记录全部显示到ListView中)
3.ifExitByEQId()方法中调用的sqlite3_get_table()可以实现和sqlite3_exec()通用的功能(只能用在查询中),但是不用回调函数。参数dbResult是一个存储所有查询结果的一维数组,索引0~nColumn中为表头,后面的是查询记录;
4.笔者建议,如果查询大量记录最好还是使用sqlite3_exec() + 回调函数的方式,避免写循环代码;如果查询单个记录或者几个记录字段时可以考虑sqlite3_get_table(),直接在调用的地方处理结果,比较实用。
开发时参考了一些网上的资料,到写本文的时候已经记不太清具体是那些了,特此声明一下。