1. CppSQLite 库

SQLite 是一个用c写的超轻量级的开源数据库;
CppSQLite3 是对SQLite进行二次封装后的C++类, 使用时需要依赖 sqlite3 库及 sqlite3.h;

在 windows 环境下使用这个类的时候,你需要确保几件事情:
1. 你要下载下面 5 个文件。 https://github.com/neosmart/CppSQLite
       CppSQLite3.h 和CppSQLite3.cpp
       sqlite3.h、sqlite3.lib 和 sqlite3.dll (windows环境)
2. 工程中引入 sqlite3.lib,最后要将CppSQLite3.h 和CppSQLite3.cpp添加到工程中 

2. 制作 CppSQLite3 动态库

// 制作 CppSQLite3 动态库
#ifdef XXXLIB_EXPORTS
#    define XXX_API  __declspec(dllexport)
#else
#    define XXX_API  __declspec(dllimport)
#endif

添加导出宏 XXX_API 及 [改进版]新增的 5 个函数

// CppSQLite3.h   
   //1. 类名前面增加导出符号 XXX_API
class XXX_API CppSQLite3Exception
class XXX_API CppSQLite3Buffer
class XXX_API CppSQLite3Binary
class XXX_API CppSQLite3Query
class XXX_API CppSQLite3Table
class XXX_API CppSQLite3Statement   // 这个是预编译,防注入用的
class XXX_API CppSQLite3DB
  // 2. CppSQLite3DB 类中增加 5 个函数
const char*   get_errormsg();
int           get_errorcode();
unsigned int  op_begin(const char *src_dbfile,const char *asdb);
unsigned int  op_append(const char *src_table,const char *dst_table,const char *key,const char *asdb);
unsigned int  op_end(const char *asdb);
 // 下面是对应的函数实现, 在 CppSQLite3.cpp 中增加
const char*  CppSQLite3DB::get_errormsg() {
    return sqlite3_errmsg(mpDB);
int  CppSQLite3DB::get_errorcode() {
    return  sqlite3_errcode(mpDB);
unsigned int CppSQLite3DB::op_begin(const char *src_dbfile,const char *asdb)
    // TODO: 判断 srcdbfile 是否文件存在    
    char sql[512];
    sprintf_s(sql,sizeof(sql),"detach database %s;",asdb);
    execDML(sql); // 分离数据库
    sprintf_s(sql, sizeof(sql),"attach DataBase '%s' as %s;",src_dbfile, asdb);
    int iError = execDML(sql);  // 附加数据库
    if ((iError) && (iError == get_errorcode()) ) {
        return -1;
    iError = execDML("begin transaction;");
    return 0;
unsigned int CppSQLite3DB::op_append(const char *src_table, const char *dst_table, const char *key, const char *asdb)
    if (!tableExists(dst_table)) {
        return 0;
    int iError = 0;
    char sql[512];
    if (key)
        sprintf_s(sql,sizeof(sql),"delete from %s where %s.%s in (select %s from %s.%s);",dst_table, dst_table,key, key, asdb, src_table);
        iError = execDML(sql);
    sprintf_s(sql,sizeof(sql),"insert into %s select A.* from %s.%s as A ;", dst_table, asdb, src_table);
    iError = execDML(sql);
    if (iError < 0) {
        return 0;
    return iError;
unsigned int CppSQLite3DB::op_end(const char *asdb)
    char sql[64];
    sprintf_s(sql,sizeof(sql),"detach database %s;",asdb);  // 分离数据库
    int iError = execDML(sql);
    iError = execDML("commit transaction;");
    if (iError < 0) {
        return 0;
    return iError;

3. sqlite 处理数据很慢的原因

sqlite在没有显式使用事务的时候会为每条 insert 都使用事务操作,而
sqlite数据库是以文件的形式存在磁盘中,就相当于每次访问时都要打开一次文件,
如果对数据进行大量的操作,时间都耗费在I/O操作上,所以很慢。
解决方法: 
显式使用事务的形式提交, 因为我们开始事务后,进行的大量操作的语句都保存在内存中,
当提交时才全部写入数据库,此时,数据库文件也就只用打开一次。

4. sqlite 处理单引号/双引号

错误处理方式:

//错误处理方式: 字符串拼接, 当 %s 本身包含 ' 或是 " 或是 一些注入攻击字符串时, 会出错.
CppSQLite3DB bsdb;
bsdb.open(file);
sprintf_s(dstsql,sizeof(dstsql),"insert into task_total (taskId,gdsId,taskName,taskBrief,taskDetail,beginTime,endTime) values (%llu,%u,'%s','%s','%s','%s','%s');",
(uint64)row[0], (DWORD)row[1], (const char*)row[2], (const char*)row[3], (const char*)row[4], (const char*)row[5],(const char*)row[6];
bsdb.execDML(dstsql);

正确处理方式:

//正确处理方式:借助 SQLite 的预编译 compileStatement 方法
char dstsql[1024]={0};
sprintf_s(dstsql, sizeof(dstsql), "INSERT INTO xxx (col1,col2,col3....) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?);");
CppSQLite3Statement stmt = bsdb.compileStatement(dstsql);
char srcsql[1024]={0};
sprintf_s(srcsql,sizeof(srcsql),"SELECT **** FROM **** WHERE ****;");
mysqlpp::Query query = sqlconn->m_conn->query(srcsql);
mysqlpp::UseQueryResult res = query.use();
for (;res;)
    mysqlpp::Row row = res.fetch_row();
    if (!row) break;
	//进行绑定
	int i = 0;
	for (;i<6; ++i)
	stmt.bind(i+1, (const int)row[i]);// int	
	for (;i<8; ++i)
	stmt.bind(i+1, (const double)row[i]);// float/double
	for (;i<16; ++i)
	stmt.bind(i+1, (const char*)row[i]);// char*		
	stmt.execDML();

参考
mysqlpp 封装了C++对MySQL操作
CppSQLite3 封装了C++对SQLite操作
CppSQLite3Statement参数绑定
SQLite 基础教程 [事务]
SQLite 基础教程 [附加]
SQLite 基础教程 [分离]

table通过使用下面语句创建:复制代码 代码如下:create table userinfo(name text, email text) 更快地插入数据 在此用time.clock()来计时,看看以下三种方法的速度。复制代码 代码如下:import sqlite3import time def create_tables(dbname):      conn = sqlite3.connect(dbname)    cursor = conn.cursor()    cursor.execute(”’create table userinfo(name text, email text)”
一:什么是sql注入   SQL注入是比较常见的网络攻击方式之一,它不是利用操作系统的BUG来实现攻击,而是针对程序员编写时的疏忽,通过SQL语句,实现无账号登录,甚至篡改数据库。 二:SQL注入攻击的总体思路    1:寻找到SQL注入的位置   2:判断服务器类型和后台数据库类型   3:针对不同的服务器和数据库特点进行SQL注入攻击 三:SQL注入攻击实例 String sql = "select * from user_table where username= ' "+us..
CREATE TABLE `xs_sessions` ( `session_uuid` VARCHAR(36) NOT NULL, `teacher_uuid` VARCHAR(36) NOT NULL, `name` VARCHAR(128) NOT NU 如果在WIN下编程,需要先用下载的源文件生成静态库文件。具体方法如下: 解压下载的sqlite-amalgamation-3180000.zip,得到的“sqlite3.h”、“sqlite3.c”、“sqlite3ext.h”三个文件添加到VS空项目中。 编译项目,生成sqlite3.dll,sqlite3.obj文件。 将sqlite3.obj文
Python sqlite3操作数据库的时候cur.execute(‘insert into t values (%d)’% num) 会被sql注入,但把占位符该成"?“就不会了。 那问题来了,”?"到底做了什么才止了sql注入呢? "?"会把参数当做值来处理,不管参数是什么,都把它插入表就完事。 而直接的字符串拼接是把参数当做SQL语句的一部分,参数中有SQL语句的话,是有可能被执行的。
如何止sql注入转载:http://www.iteye.com/topic/617072 SQL注入攻击的总体思路: 发现SQL注入位置;判断服务器类型和后台数据库类型;确定可执行情况 对于有些攻击者而言,一般会采取sql注入法。下面我也谈一下自己关于sql注入法的感悟。注入法: 从理论上说,认证网页中会有型如: select * from admin where username=’X
SQLite3是一款轻量级的关系型数据库管理系统,它是以C语言写成的,并且提供了C语言的API接口。要在C++中使用SQLite3,可以使用SQLite C/C++接口,该接口包含在SQLite3的源代码中,可以通过下载SQLite3的源码来获得。 以下是在C++中使用SQLite3的基本步骤: 1. 下载SQLite3的源代码并解压缩。 2. 在C++项目中添加SQLite3的源代码文件。 3. 在需要使用SQLite3的地方包含SQLite3的头文件: ```c++ #include <sqlite3.h> 4. 打开数据库连接: ```c++ sqlite3* db; int rc = sqlite3_open("database.db", &db); if(rc != SQLITE_OK) { // 连接失败 这里的`database.db`是数据库文件的名称,如果该文件不存在,则会自动创建。 5. 执行SQL语句: ```c++ char* errmsg; int rc = sqlite3_exec(db, "CREATE TABLE IF NOT EXISTS users(id INTEGER PRIMARY KEY, name TEXT, age INTEGER)", nullptr, nullptr, &errmsg); if(rc != SQLITE_OK) { // 执行SQL语句失败 上面的SQL语句创建了一个名为`users`的表,该表包含三个字段:`id`、`name`和`age`。 6. 查询数据: ```c++ sqlite3_stmt* stmt; int rc = sqlite3_prepare_v2(db, "SELECT * FROM users", -1, &stmt, nullptr); if(rc != SQLITE_OK) { // 查询失败 while(sqlite3_step(stmt) == SQLITE_ROW) { int id = sqlite3_column_int(stmt, 0); const char* name = (const char*)sqlite3_column_text(stmt, 1); int age = sqlite3_column_int(stmt, 2); // 处理查询结果 sqlite3_finalize(stmt); 上面的代码查询了`users`表中的所有数据,并逐行读取数据。`sqlite3_prepare_v2`函数用于准备SQL语句,`sqlite3_step`函数用于执行SQL语句并读取结果,`sqlite3_finalize`函数用于释放资源。 7. 关闭数据库连接: ```c++ sqlite3_close(db); 关闭数据库连接会释放所有相关资源,包括打开的文件句柄、内存等。 SQLite3的API接口非常简单,使用起来也比较方便,但需要注意的是,SQLite3不支持并发访问,因此在多线程环境中使用时需要注意线程安全问题。