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添加到工程中
#ifdef XXXLIB_EXPORTS
# define XXX_API __declspec(dllexport)
#else
# define XXX_API __declspec(dllimport)
#endif
添加导出宏 XXX_API 及 [改进版]新增的 5 个函数
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
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);
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)
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;
sqlite在没有显式使用事务的时候会为每条 insert 都使用事务操作,而
sqlite数据库是以文件的形式存在磁盘中,就相当于每次访问时都要打开一次文件,
如果对数据进行大量的操作,时间都耗费在I/O操作上,所以很慢。
解决方法:
显式使用事务的形式提交, 因为我们开始事务后,进行的大量操作的语句都保存在内存中,
当提交时才全部写入数据库,此时,数据库文件也就只用打开一次。
错误处理方式:
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);
正确处理方式:
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]);
for (;i<8; ++i)
stmt.bind(i+1, (const double)row[i]);
for (;i<16; ++i)
stmt.bind(i+1, (const char*)row[i]);
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不支持并发访问,因此在多线程环境中使用时需要注意线程安全问题。