SQLITE3 在C/C++ 中的应用
1.准备SQLite源文件
首先去SQLite官网去下载源文件:官网网站
如果在WIN下编程,需要先用下载的源文件生成静态库文件。具体方法如下:
- 解压下载的sqlite-amalgamation-3180000.zip,得到的“sqlite3.h”、“sqlite3.c”、“sqlite3ext.h”三个文件添加到VS空项目中。
- 编译项目,生成sqlite3.dll,sqlite3.obj文件。
- 将sqlite3.obj文件复制到VS文件夹中lib.exe所在目录下,用管理员权限打开cmd,输入命令:lib sqlite3.obj,生成静态库sqlite3.lib。
- 将sqlite3.lib和sqlite3.h添加到需要编译的VS项目中就可以使用SQLite了。
在Linux下使用不用执行这一步,具体使用方法后面会提到。
2.SQLite Interface
在C/C++中使用SQLite最重要的三个接口就是sqlite3_open、sqlite3_exec和sqlite3_close,有了这三个接口就能简单的使用数据库了。
sqlite3_open用于打开并连接到SQLite数据库,并返回一个连接对象。
sqlite3_exec用于执行SQL语句,运行时,需要配套一个SQL语句和一个回调函数,执行时,数据库会把SQL语句进行解析,然后编译,最后去执行。
sqlite3_close用于断开与SQL数据库的连接,如果仍有未完成的查询,sqlite3_close将返回SQLITE_BUSY,并显示错误消息。
如果遇到需要重复或者循环执行SQL语句的情况,选择使用sqlite3_exec函数会反复执行解析和编译过程,效率会非常低。
遇到这种情况时,推荐大家使用sqlite3_stmt这个数据结构。sqlite3_stmt的使用方法如下:
- 利用sqlite3_prepare_v2()创建stmt对象。
- 调用sqlite_bind将应用程序的数据存储到原始SQL的参数中。
- 调用一次或者多次sqlite3_step去执行语句。
- 如果需要执行多次sqlite3_step,需要使用sqlite3_reset()去重置stmt对象, 然后执行步骤2,重新赋值。
- 整个操作完成后,调用sqlite3_finalize()去销毁并释放stmt对象
上面提到的接口在SQL官网中有详细的介绍,这里不具体展开说明,想了解的朋友可以自己查一下,链接在这SQLite Interface。在重复执行SQL语句的时候,相比sqlite3_exec,利用stmt对象,只需要用sqlite3_prepare_v2函数对SQL语句执行一次解析、编译,sqlite3_step执行多次,这样减少了解析和编译的次数,效率会提高很多。
3.实例
前面提到了在WINDOW下使用SQLite的方法,在LINUX下就不需要那么多繁琐的步骤了,在生成目标文件的时候,记得加上sqlite3.c源文件就可以了,详见3.4 CMakeLists.txt。下面附上代码。
3.1 create database
//createtable.c
#include <stdio.h>
#include <stdlib.h>
#include <sqlite3.h>
static 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;
}
int main(int argc, char* argv[])
{
sqlite3 *db;
char *zErrMsg = 0;
int rc;
char *sql;
/* Open database */
rc = sqlite3_open("test.db", &db);
if( rc ){
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
return(0);
}else{
fprintf(stdout, "Opened database successfully\n");
}
/* Create SQL statement */
sql = "CREATE TABLE SCHOOL(" \
"NUM INT PRIMARY KEY NOT NULL," \
"NAME TEXT NOT NULL," \
"AGE INT NOT NULL," \
"SEX CHAR(50));" ;
/* Execute SQL statement */
rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg);
if( rc != SQLITE_OK ){
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}else{
fprintf(stdout, "Table created successfully\n");
}
sqlite3_close(db);
return 0;
}
3.2 insert value
//insert.c
#include <sqlite3.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
typedef enum {
index_key = 1,
index_name,
index_age,
index_sex,
}INDEX_EN;
typedef struct{
char name[10];
int age;
char sex[10];
}INPUTDATA_ST;
id insertData(int key, void *data);
sqlite3* sqldb1 = NULL;
void main(void)
{
int mInputCount = 0;
char *zErrMSG = NULL;
int len = 0;
int res = sqlite3_open("test.db", &sqldb1);
if( !res ){
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(sqldb1));
}else{
fprintf(stdout, "Opened database successfully\n");
}
INPUTDATA_ST inputdata;
memset(&inputdata, 0 ,sizeof(INPUTDATA_ST));
strcpy(inputdata.name, "TONG");
inputdata.age = 19;
strcpy(inputdata.sex, "male");
char data[50];
memset(data, 0 ,sizeof(data));
memcpy(data, &inputdata, sizeof(inputdata));
insertData(1, data);
}
void insertData(int key, void *data)
{
const char* sql = NULL;
sql = "INSERT INTO SCHOOL (NUM,NAME,AGE,SEX) VALUES(?,?,?,?);";
sqlite3_stmt* stmt = NULL;
const char *pzTail = NULL;
INPUTDATA_ST *inputdata = (INPUTDATA_ST *)data;
sqlite3_prepare_v2(sqldb1, sql, -1, &stmt, &pzTail);
sqlite3_bind_int(stmt, index_key, key);
sqlite3_bind_text(stmt, index_name, inputdata->name, strlen(inputdata->name), SQLITE_STATIC);
sqlite3_bind_int(stmt, index_age, inputdata->age);
sqlite3_bind_text(stmt, index_sex, inputdata->sex, strlen(inputdata->sex), SQLITE_STATIC);
int res = sqlite3_step(stmt);
if(res == SQLITE_DONE){
printf("Insert success.\n");
}else{
printf("Insert failed. Errorcode = %d.\n",res);
}
sqlite3_reset(stmt);
sqlite3_finalize(stmt);
}
3.3 Select value
#include <stdio.h>
#include <stdlib.h>
#include <sqlite3.h>
static 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;
}
int main(int argc, char* argv[])
{
sqlite3 *db;
char *zErrMsg = 0;
int rc;
char *sql;
/* Open database */
rc = sqlite3_open("test.db", &db);
if( rc ){
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
return(0);
}else{
fprintf(stderr, "Opened database successfully\n");
}
/* Create SQL statement */
sql = "SELECT * FROM SCHOOL ";
/* Execute SQL statement */
rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg);
if( rc != SQLITE_OK ){
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}else{
fprintf(stdout, "Records created successfully\n");
}
sqlite3_close(db);
return 0;
}
3.4 CMakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.10)
ADD_EXECUTABLE(create ${PROJECT_SOURCE_DIR}/src/createtable.c sqlite3.c)
ADD_EXECUTABLE(insert ${PROJECT_SOURCE_DIR}/src/insert.c sqlite3.c)
ADD_EXECUTABLE(select ${PROJECT_SOURCE_DIR}/src/select.c sqlite3.c)
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/include)
TARGET_LINK_LIBRARIES(create pthread dl)
TARGET_LINK_LIBRARIES(insert pthread dl)
TARGET_LINK_LIBRARIES(select pthread dl)
最后附上运行结果: